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

Internet Relay Chat internet.relay.chat at gmail.com
Sun Feb 5 22:28:57 CET 2006


El método más sencillo que se me ocurre es, simplemente, que cuando se 
agreguen nuevos registros no nulos a la tabla n, el nodo verifique si tiene 
de forma local algún usuario con ese nick y sin el flag +r, y, en el caso de 
que tenga alguno, efectúe un KILL con un motivo como "Uso no autorizado de 
nick registrado".

-Esto permite maximizar el uso de los servidores, puesto que bloquear los 
accesos a un servidor que pretende estar 24/365 y que se le conecte el mayor 
número posible de usuarios no parece la mejor idea.
-Es además compatible hacia atrás. Pueden convivir perfectamente nodos con y 
sin el parche.
-Los accesos no autorizados al nodo son rápidamente eliminados, ya que el 
tiempo de copiado de la tabla es muy rápido (¿en eso quedamos, no?).
-No afectaría al registro de nicks, puesto que en ese momento el usuario 
debería haber recibido el rename.
-Los usuarios que puedan confundirse al ver un jcea, quedan desengañados al 
ver el mensaje de salida (si fuera un RENAME podrían creer que es... ¿un 
usuario registrado registrándose el nick?). Y si se tratara de un caso de 
que la tabla no estuviese actualizada por un split... se supone que si es un 
usuario lo suficientemente importante como para que su nick se reconozca 
fácilmente no va a acabar de registrarlo por lo que el nodo en split tendrá 
un registro para el mismo.


Y ahora alejándonos un poco ya del tema...
  -Da gusto ver un poco de mensajes de irc.

  -Recibí las dos respuestas antes que el original (que recibí/leí hoy)... 
hubo algún motivo en especial o es un retraso normal de emails? (para el 
poco tráfico que tiene, va y se pierde por el camino :P)

  -No sé cuando tomaste esos datos, pero en estos momentos los datos de la 
tabla n en hispano son:
Tabla 'n' S=010399753 R=000111503 (hace un rato era Tabla 'n' S=010399668 
R=000111498), esto es: 5 nuevos registros y 85 modificaciones!!! Ciertamente 
parece interesante compactarla...

 -JCea, parece que el estar dos años desvinculado del tema es literal, 
puesto que un nick info en hispano da:
<NiCK> RealName de 12jcea es 12http://www.argo.es/~jcea/
<NiCK> Hora de registro: 1210:57:32 04/Ene/1999 CET
<NiCK> Ultima hora por la red: 1212:30:37 10/Nov/2004 CET
<NiCK> Nick migrado a BDD
<NiCK> URL: 12http://www.argo.es/~jcea/
<NiCK> Opciones: 1212Seguro,12Privado
<NiCK> Fin de INFO

No obstante unos emails atrás (marzo 2005) habías hablado dicho "Yo ya solo 
entro al IRC para que no me caduque el nick :-p" (con lo que suponía que 
entrabas). Tras lo que negaste tener un "noexpire infinito" (que simplemente 
era la opción de que no expirase)..... ¿cómo lo has hecho para que no te 
caduque?

Saludos

----- Original Message ----- 
From: "Jesus Cea" <jcea at argo.es>
To: <irc-dev at argo.es>
Sent: Saturday, February 04, 2006 10:51 PM
Subject: [IRC-DEV] Base de datos distribuida y arranque "frío" de nodos


-----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 :-)





More information about the IRC-Dev mailing list