Pregunta

Tengo aplicaciones agrupadas que requieren que uno de los nodos sea designado como maestro. Los nodos del clúster se rastrean en una tabla con nodeID , isMaster , lastTimestamp columnas.

Cada nodo del clúster intentará convertirse en maestro cada X segundos. Nodo solo puede convertirse en un maestro si cualquiera

  • no hay otros nodos maestros
  • la lastTimestamp en el nodo maestro actual es anterior por 2*X

Cuando se cumple una de las condiciones anteriores

  • el isMaster del nodo maestro actual debe borrarse
  • se debe establecer isMaster del nuevo nodo maestro
  • la lastTimestamp del nuevo nodo maestro debe establecerse en la marca de hora "ahora".

¿Cuál es la instrucción SQL única (portátil) para lograr lo anterior sin la posibilidad de que dos o más nodos se conviertan en maestros?

¿Fue útil?

Solución

¿No es este tipo de coordinación normalmente manejada por el DBMS mismo, en lugar de por aplicaciones que se ejecutan en el DBMS? Yo también puedo imaginar formas de hacerlo en el DBMS con el que estoy familiarizado, pero sin saber más sobre su sistema (presumiblemente está usando discos compartidos, por lo que todos los nodos ven los mismos datos; presumiblemente hay protocolos de bloqueo que impiden el acceso concurrente a los datos; es un proceso de usuario en el nodo maestro que actualiza periódicamente la última marca de tiempo), va a ser difícil ayudar mucho. Y, como señaló Jamie Love, el DBMS debería permitir que múltiples procesos coordinen el acceso a los registros relevantes, siendo el registro principal relevante el registro maestro actual.

[ Editado : Tal vez estaba leyendo demasiado en él.

La única instrucción UPDATE debe realizar actualizaciones diferenciales en dos filas de la tabla y debe fallar si solo es posible una de las dos actualizaciones. Es decir, debe cambiar el maestro actual para que no sea maestro y también cambiar su propio registro para que sea el maestro. Un problema es cómo el DBMS impone la restricción "solo una fila puede ser la maestra". Supongamos que funciona y la declaración en su conjunto fallará si hay un problema, como debería ser. ¿Por qué las personas a menudo omiten el nombre de la tabla, incluso cuando proporcionan los nombres de columna? Ah, bueno, el nombre de la tabla es en adelante ClusterControl . Cada nodo debe conocer su propio NodeID de alguna manera; He usado {MyNodeID} para indicar dónde aparece eso en el SQL.

Necesita una actualización de latidos por separado:

 UPDATE ClusterControl
     SET lastTimestamp = CURRENT_TIMESTAMP
     WHERE NodeID = {MyNodeID};

El " tomar el estado maestro " la actualización podría ser:

UPDATE ClusterControl
    SET lastTimestamp = (CASE
                         WHEN NodeID = {MyNodeID} THEN CURRENT_TIMESTAMP
                         ELSE lastTimestamp END),
        isMaster      = (CASE
                         WHEN NodeID = {MyNodeId} THEN 'Y'
                         ELSE 'N' END)
    WHERE (NodeID  = {MyNodeID} AND isMaster = 'N') OR
          (NodeID != {MyNodeID} AND
           lastTimestamp < CURRENT_TIMESTAMP - INTERVAL '120' SECOND AND
           isMaster = 'Y'
          );

La teoría detrás de la actualización 'seize master status' es (cláusula SET):

  • el campo lastTimestamp para el nuevo maestro se establece en la marca de tiempo actual, pero el maestro anterior no cambia.
  • el campo isMaster se cambia a 'Y' para el nuevo maestro y a 'N' para el antiguo maestro.

La teoría detrás de la cláusula WHERE es:

  • Cambie solo el registro para el nodo actual si no es el maestro actual o el registro para el nodo maestro actual cuando este nodo no es el nodo actual y la marca de tiempo es más de 120 segundos (" 2 * X " en la pregunta) de edad.

Dado que existe una restricción (posiblemente mítica) para garantizar que solo una fila tenga el indicador 'Y', esto debería fallar según sea necesario cuando el maestro esté actualizado.

SQL no probado

]

Otros consejos

Puedo imaginar una solución para una base de datos Oracle, pero no estoy seguro de que sea portátil. ¿Por qué esto debe ser una sola declaración SQL portátil? La mayoría de las bases de datos permiten el bloqueo de tablas y las transacciones, que le permiten hacer este tipo de cosas en varias declaraciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top