[IRC-DEV] Base de datos distribuida y arranque "frío" de nodos

Jesus Cea jcea at argo.es
Sat Feb 4 22:51:15 CET 2006


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Un mensaje de IRC-DEV, para variar :-). Que no se diga...

Documento el tema aquí para que conste en algún sitio y no se pierda
"como lágrimas en la lluvia". Enseñanza a generaciones futuras, etc,
etc. :-)


Uno de los problemas que recuerdo de mi época de IRC-Hispano (hace casi
dos añitos que estoy desvinculado del tema :) es que cuando entraba un
nodo "nuevo" o bien un nodo en producción detectaba cualquier tipo de
problema con la Base de Datos Distribuida (en adelante BDD) y la
borraba, los usuarios podían conectar a dicho nodo sin autentificación,
durante un tiempo.

Para los servicios de Olimpo no había ningún problema, porque el acceso
a los mismos requería el modo "+r" y dichos usuarios no lo tenían. Pero
en cualquier caso ver a un usuario "sisco" o "jcea" falsos se prestaba a
confusión entre los usuarios.

Tocar este asunto era uno de los temas pendientes cuando dejé el
desarrollo en IRC-Hispano. Planteo el asunto aquí por si alguien se
anima a meterle mano. Es muy fácil.

El problema es que un nodo no debería permitir el acceso de usuarios si
su base de datos no está actualizada o, al menos, "relativamente"
actualizada. Debería rechazar a los usuarios de forma temporal con un
error claro y apropiado, mientras no tenga sus BDDs actualizadas. Con
los parámetros de hace dos años de IRC-Hispano, una actualización de
100.000 registros llevaba cosa de 5 segundos, así que la restricción
debería levantarse enseguida.

En este momento IRC-Hispano tiene 884359 registros en su tabla "n"
(Glog, un día de estos haz una compactación :-), la mayoría de los
cuales se podrían eliminar mediante compactación. Ya no son válidos por
cambios de clave o expiraciones de los nicks. De hecho revisando la BDD,
los registros reales en la tabla "n" son 111.460.

Aunque todos fuesen correctos y la BDD estuviese limpita y compactada
(que no es el caso :), transferir esos registros "en frío" supondría
menos de un minuto. En cualquier caso, no debería ser problema.

Por tanto propongo dos soluciones para el tema de la BDD "anticuada":

1. Todo nodo guarda el número de registro más alto que ha visto ALGUNA
VEZ en cada una de las BDD. Un nodo debe rechazar cualquier intento de
conexión de usuarios si alguno de dichos valores es SUPERIOR al valor
correspondiente actual de alguna BDD. Es decir, el nodo recuerda "donde
iba" en cada BDD, y si tiene que borrar alguna base de datos, rechazará
usuarios hasta que las BDDs estén actualizadas al menos hasta el punto
original.

 El problema de este esquema es que un nodo "nuevo", uno recién
instalado, o al que se le haya hecho "limpieza", etc., pueden haber
perdido esa información histórica, con lo que estaríamos en la posición
original. Algo se ha ganado, pero no es la panacea.

Otra opción:

2. Añadir una clave adicional en la tabla ¿z? (la que lleva cosas como
la longitud de los nicks, activación de IPs virtuales personalizadas,
etc. Hablo de memoria) con el nombre "timestamp". El campo de datos de
dicha clave será un "timestamp" en segundos desde el epoch y una serie
de números. Cada número es el número de registro de una BDD en el
instante señalado por el "timestamp" del primer campo.

 Cada nodo guardará el número de registro que desea alcanzar en cada BDD
antes de dar acceso a los usuarios. Inicialmente, cuando se arranca el
servidor, esos valores serán 2^31. Osea, no deja entrar a ni dios.

 Cuando relee la base de datos en disco o le llega el registro
"timestamp" por la red, comprueba el valor de "timestamp" que le entra
con su fecha local. Si la diferencia es mayor de, digamos, 12 horas,
simplemente no hace nada con el registro.

 En cambio si el timestamp es "reciente", actualiza los números de
registro mínimos necesarios en las BDD con los valores que le entra. Si
ya ha llegado a ese mínimo, permite acceso a usuarios. Si todavía no ha
llegado, los sigue denegando.

Este segundo esquema es mucho más robusto, ya que funciona incluso
aunque sea un nodo recién instalado o "limpiado". Sólo permitirá el
acceso al nodo de IRC si las BDD tienen una antigüedad inferior a,
digamos, 12 horas. Si no es el caso, no te deja entrar. Dado que el
IRCD, de fondo, va pillando las BDDs de la red, eventualmente (segundos)
determinará que sus BDD están lo bastante actualizadas y permitirá el
acceso a los usuarios.

El único problema de este esquema es que se requiere que "algo" inyecte
en la red un nuevo registro "timestamp" cada, digamos, cuatro horas. Si
dicho proceso muere, pierde la conexión a internet o a alguien se le ha
olvidado tocar el botón apropiado, la red entera denegará el acceso a
los usuarios. Por supuesto, no es imprescindible que dicho "timestamp"
lo genere un único nodo. Puede haber varios, repartidos por la red. Sólo
hay que tener cuidado porque el diseño de la BDD presupone que cada BDD
(hay 26) se actualiza exclusivamente desde un sitio. Pero si esos nodos
de control se coordinan entre sí para evitar colisiones en los números
de registros, es factible. Por ejemplo, usar un esquema de mayorías.

Dos notas finales:

- - Si hay un split muy prolongado de la red, la mitad "pobre" puede
empezar a rechazar usuarios. La solución más obvia es fijar un timeout
muy elevado. Por ejemplo, en vez de 12 horas, fijar un tiempo límite de
7 días. Si hay un split de siete días, mejor que rechaces usuarios :-p

- - Los números de secuencia en el "timestamp" *NO DEBEN* corresponder a
los números actuales de la BDD, sino a, digamos, los que tenía hace
media hora. ¿Por qué?. Porque si un nodo entra desde un split, recibirá
con toda probabilidad el registro "timestamp" ANTES de haber recibido el
resto de las BDD, y rechazará usuarios durante el "burst". Otra opción
simple es tener dos juegos de valores de registro de BDD alternativos:
Uno del "timestamp" actual y otro del inmediatamente ANTERIOR. El válido
es el ANTERIOR. Cuando llega un "timestamp" nuevo, sus valores pasan a
la reserva y el anterior pasa a ser efectivo. Si los timestamps, como se
comenta en el punto anterior, tienen una validez de días, no rechazas a
nadie.

Algo a valorar es la posibilidad de modificar el algoritmo de
"timestamp" ante splits y similares. Eso queda para quien tenga tiempo y
ganas de pensar un poco.

Hale, a darle al coco :-)

- --
Jesus Cea Avion                         _/_/      _/_/_/        _/_/_/
jcea at argo.es http://www.argo.es/~jcea/ _/_/    _/_/  _/_/    _/_/  _/_/
                                      _/_/    _/_/          _/_/_/_/_/
PGP Key Available at KeyServ   _/_/  _/_/    _/_/          _/_/  _/_/
"Things are not so easy"      _/_/  _/_/    _/_/  _/_/    _/_/  _/_/
"My name is Dump, Core Dump"   _/_/_/        _/_/_/      _/_/  _/_/
"El amor es poner tu felicidad en la felicidad de otro" - Leibniz
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQCVAwUBQ+Uh05lgi5GaxT1NAQLssQP+JD/Sh1HEmD2otY/qvqyyJ4EAxblLCRos
Wc59wiXNHbiCH7tVvwWo4WlU3wi42CJRp1KYvdlkL8e4DM7zimsxrVDGH+hwNnlz
JXifnn53AdAW+3Bh/WuG/CPwFuEYYPH5bg80WrpHVHnxooS4JntvzJoBIefjVPIq
waAcbvOP1y0=
=X0b4
-----END PGP SIGNATURE-----



More information about the IRC-Dev mailing list