cassandra - insertar - Creación de una nueva tabla con cqlsh en el espacio de claves existente: discrepancia de ID de familia de columnas
guia cassandra (2)
Houston, tenemos un problema.
Intentar crear una nueva tabla con cqlsh
en un cqlsh
de cqlsh
Cassandra (v2.1.3) existente da como resultado:
ServerError:
<ErrorMessage code=0000 [Server error] message="java.lang.RuntimeException:
java.util.concurrent.ExecutionException:
java.lang.RuntimeException:
org.apache.cassandra.exceptions.ConfigurationException: Column family ID mismatch (found e8c03790-c952-11e4-a753-5981ea73cd7c; expected e8b14370-c952-11e4-a844-8f10bfb9c386)">
Después del primer intento de creación, intentar una vez más resultará en:
AlreadyExists: la tabla ''ks.metrics'' ya existe
Pero recuperando la lista de tablas existentes para las desc tables;
del espacio de desc tables;
no reportará la nueva tabla.
El problema parece estar relacionado con Cassandra-8387 excepto que solo hay un cliente que intenta crear la tabla: cqlsh
Tenemos un montón de trabajos de Spark que crearán los espacios de claves y las tablas en el inicio, posiblemente haciendo esto en paralelo. ¿Esto haría que el espacio de claves sea corrupto?
Crear un nuevo espacio de teclas y agregarle una tabla funciona como se espera.
¿Algunas ideas?
ACTUALIZAR
Encontró una solución alternativa: realice una reparación en el espacio de teclas y aparecerán las tablas ( desc tables
) y también son funcionales.
Tuve dos esquemas de tablas diferentes con el mismo nombre de tabla por error. así que ocurrió este problema (estaba usando express-cassandra
)
Respuesta corta: tienen una condición de raza , que creen que resolvieron en 1.1.8 ...
Respuesta larga:
Recibo ese error todo el tiempo en uno de mis grupos. Tengo máquinas de prueba que tienen unidades de disco duro muy lentas y crear una o dos tablas es suficiente para obtener el error cuando tengo 4 nodos en dos computadoras separadas.
Debajo tengo una copia del seguimiento de pila de mi instalación de Cassandra 3.7. Aunque su versión era 2.1.3, me sorprendería que esta parte del código haya cambiado tanto.
Como podemos ver, la excepción ocurre en la función validateCompatibility()
. Esto requiere que las versiones nuevas y antiguas de MetaData tengan las mismas características:
- ksName (nombre del espacio de teclas)
- cfName (nombre de la familia de columnas)
- cfId (columnfamily UUID)
- banderas (isSuper, isCounter, isDense, isCompound)
- comparador (comparador de clasificación de teclas)
Si alguno de estos valores no coincide entre los metadatos antiguos y los nuevos, entonces el proceso genera una excepción. En nuestro caso, los valores de cfId
son diferentes.
Subiendo la pila, tenemos el apply()
que llama a validateCompatibility()
inmediatamente.
A continuación tenemos updateTable()
. Del mismo modo, llama a apply()
casi inmediatamente. Primero, llama a getCFMetaData()
para recuperar los datos de la familia de columnas actuales ("antiguos") que se compararán con los datos nuevos.
A continuación vemos updateKeyspace()
. Esa función calcula una diff
para saber qué ha cambiado. Luego guarda eso en cada tipo de datos. La tabla es la segunda después del tipo ...
Antes de eso, tienen el mergeSchema()
que calcula lo que cambió en el nivel de Keyspace. A continuación, elimina los espacios de claves que se eliminaron y genera nuevos espacios de claves para aquellos que se actualizaron (y para nuevos espacios de claves). Finalmente, updateKeyspace()
los nuevos updateKeyspace()
llaman a updateKeyspace()
para cada uno de ellos.
A continuación en la pila vemos una función interesante: mergeSchemaAndAnnounceVersion()
. Éste actualizará la versión una vez que los espacios de claves se hayan actualizado en la memoria y en el disco. La versión del esquema incluye ese cfID
que no es compatible y, por lo tanto, genera la excepción. La parte Announce
es enviar un mensaje de chisme a los otros nodos sobre el hecho de que este nodo ahora conoce la nueva versión de un determinado esquema.
A continuación vemos algo llamado MigrationTask
. Este es el mensaje utilizado para migrar los cambios entre los nodos de Cassandra. La carga útil del mensaje es una colección de mutaciones (aquellas manejadas por la función mergeSchema()
).
El resto de la pila solo muestra las run()
que son varios tipos de funciones usadas para manejar mensajes.
En mi caso, para mí el problema se resuelve un poco más tarde y todo está bien. No tengo nada que hacer para que el esquema finalmente se sincronice. como se esperaba. Sin embargo, me impide crear todas mis tablas de una sola vez. Por lo tanto, mi opinión es que los mensajes de migración no llegan en el orden esperado. Debe haber un tiempo de espera que se maneja al reenviar el evento y que genera la mezcla.
Entonces, veamos el código que envía el mensaje en primer lugar, usted ve ese en el MigrationManager. Aquí tenemos un parámetro MIGRATION_DELAY_IN_MS
relacionado con un problema anterior, la carrera de empujar / tirar del esquema , que era para evitar una condición de carrera. Bueno, allá vas. Entonces, son conscientes de que existe una posible condición de carrera y, para intentar evitarla, agregaron un poco de retraso allí. Una parte de esa corrección incluye una revisión de versión. Si las versiones ya son iguales, evite la actualización por completo (es decir, ignore ese chisme).
if (Schema.instance.getVersion().equals(currentVersion))
{
logger.debug("not submitting migration task for {} because our versions match", endpoint);
return;
}
El retraso del que estamos hablando es de un minuto:
public static final int MIGRATION_DELAY_IN_MS = 60000;
Uno pensaría que un minuto entero sería suficiente, pero de alguna manera todavía obtengo el error todo el tiempo.
El hecho es que su código no espera que ocurran varios cambios uno tras otro, lo que incluye grandes retrasos como los que tengo. Así que si tuviera que crear una tabla y luego hacer otras cosas, estaría bien. Por otro lado, cuando quiero crear 20 tablas seguidas en esas máquinas lentas, el mensaje de chismes de un cambio de esquema anterior llega tarde (es decir, después de que el nuevo comando CREAR TABLA llegó a ese nodo). . La peor parte, supongo, es que es un error espurio (es decir, me dice que el chisme fue posterior, y no que mi esquema no sea válido y que el esquema en el mensaje de chismes sea antiguo).
org.apache.cassandra.exceptions.ConfigurationException: Column family ID mismatch (found 122a2d20-9e13-11e6-b830-55bace508971; expected 1213bef0-9e
at org.apache.cassandra.config.CFMetaData.validateCompatibility(CFMetaData.java:790) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.config.CFMetaData.apply(CFMetaData.java:750) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.config.Schema.updateTable(Schema.java:661) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.schema.SchemaKeyspace.updateKeyspace(SchemaKeyspace.java:1350) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.schema.SchemaKeyspace.mergeSchema(SchemaKeyspace.java:1306) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.schema.SchemaKeyspace.mergeSchemaAndAnnounceVersion(SchemaKeyspace.java:1256) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.service.MigrationTask$1.response(MigrationTask.java:92) ~[apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.net.ResponseVerbHandler.doVerb(ResponseVerbHandler.java:53) [apache-cassandra-3.9.jar:3.9]
at org.apache.cassandra.net.MessageDeliveryTask.run(MessageDeliveryTask.java:64) [apache-cassandra-3.9.jar:3.9]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_111]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]