cassandra distributed apache-storm

cómo incrementar rápidamente los contadores en Cassandra sin estanqueidad



distributed apache-storm (3)

La versión actual de los contadores simplemente no es una buena opción para un caso de uso que requiere garantías de no contar en exceso y de consistencia inmediata.

Hay operaciones de incremento y decremento, que no chocarán entre sí, y, a menos que haya mutaciones perdidas o mutaciones repetidas, le dará un resultado correcto.

La reescritura de los contadores de Cassandra ( https://issues.apache.org/jira/browse/CASSANDRA-6504 ) puede ser interesante para usted, y debe abordar todas las inquietudes actuales para obtener el recuento correcto.

Mientras tanto, si tuviera que implementar esto en la parte superior de una versión actual de Cassandra, y un recuento preciso era esencial, probablemente almacenaría cada incremento o decremento como una columna y realizaría una agregación de los resultados en tiempo de lectura mientras escribía retroceda un punto de control para que no tenga que volver a leer al principio de los tiempos para calcular los resultados posteriores.

Esto agrega mucha carga al lado de lectura, aunque es extremadamente eficiente en la ruta de escritura, por lo que puede o no funcionar para su caso de uso.

Tengo una pregunta de Cassandra. ¿Sabes cómo Cassandra hace actualizaciones / incrementos de contadores?

Quiero usar un perno de tormenta (CassandraCounterBatchingBolt del repositorio storm-contrib en github) que escribe en cassandra. Sin embargo, no estoy seguro de cómo funciona algo de la implementación del método incrementCounterColumn () ... y también existen las limitaciones con los contadores de cassandra (de: http://wiki.apache.org/cassandra/Counters ) que los hace Inútil para mi escenario IMHO:

  • Si una escritura falla inesperadamente (tiempo de espera o pérdida de conexión con el nodo coordinador), el cliente no sabrá si la operación se ha realizado. Un reintento puede resultar en un conteo excesivo CASSANDRA-2495.

  • La eliminación del contador es intrínsecamente limitada. Por ejemplo, si emite muy rápidamente la secuencia "incremento, eliminación, incremento", es posible que la eliminación se pierda

De todos modos, aquí está mi escenario:
Actualizo el mismo contador más rápido que las actualizaciones se propagan a otros nodos de Cassandra.

Ejemplo :
Digamos que tengo 3 nodos cassandra. Los contadores en cada uno de estos nodos son 0.
Nodo1: 0, nodo2: 0, nodo3: 0

Un incremento viene: 5 -> Nodo1: 0, nodo2: 0, nodo3: 0

El incremento comienza en el nodo 2: aún debe propagarse a nodo1 y nodo3
Nodo1: 0, nodo2: 5, nodo3: 0

Mientras tanto, otro incremento llega antes del incremento anterior
se propaga: 3 -> Nodo1: 0, nodo2: 5, nodo3: 0

Suponiendo que 3 comiencen en un nodo diferente de donde comenzó 5 tenemos:
Nodo1: 3, nodo2: 5, nodo3: 0

Ahora, si 3 se propaga a los otros nodos COMO UN INCREMENTO y no como un nuevo valor (y lo mismo para 5), ​​eventualmente los nodos serían todos iguales a 8 y esto es lo que quiero.

Si 3 sobrescribe 5 (porque tiene una marca de tiempo posterior) esto es problemático, no es lo que quiero.

¿Sabes cómo Cassandra maneja estas actualizaciones / incrementos?

Tenga en cuenta que una lectura antes de una escritura todavía es susceptible al mismo problema dependiendo de qué nodo de réplica se ejecute la lectura (el quórum todavía puede fallar si la propagación no está muy avanzada)

También estoy pensando que tal vez poner un caché entre mi tormenta y Cassandra podría resolver este problema, pero esa es una historia para otro momento.


Los contadores en C * tienen una representación interna compleja que evita la mayoría (pero no todos) los problemas de contar cosas en un sistema distribuido sin líderes. Me gusta pensar en ellos como contadores fragmentados. Un contador consta de una cantidad de sub-contadores identificados por la ID del host y un número de versión. El host que recibe la operación de contador incrementa solo su propio contador secundario, y también incrementa la versión. Luego replica todo su estado contrario a las otras réplicas, que lo combinan con sus estados. Cuando se lee el contador, el nodo que maneja la operación de lectura determina el valor del contador al sumar el total de los conteos de cada host.

En cada nodo, un incremento de contador es como todo lo demás en Cassandra, solo una escritura. El incremento se escribe en el memtable, y el valor local se determina en el momento de la lectura combinando todos los incrementos del memtable y todos los SSTables.

Espero que la explicación te ayude a creerme cuando te digo que no tienes que preocuparte por aumentar los contadores más rápido de lo que Cassandra puede manejar. Dado que cada nodo mantiene su propio contador y nunca replica operaciones de incremento, no hay posibilidad de que los recuentos se pierdan debido a las condiciones de la carrera, como lo haría un escenario de lectura-modificación-escritura. Si Cassandra acepta la escritura, tienes la garantía de que contará.

Sin embargo, lo que no está garantizado es que el recuento aparecerá correcto en todo momento a menos que. Si un incremento se escribe en un nodo pero el valor del contador se lee en otro justo después, no hay garantía de que el incremento se haya replicado, y también debe considerar lo que sucedería durante una partición de red. Esto es más o menos lo mismo con cualquier escritura en Cassandra, está en su naturaleza finalmente consistente y depende de los niveles de consistencia que usó para las operaciones.

También existe la posibilidad de un reconocimiento perdido. Si haces un incremento y pierdes la conexión con Cassandra antes de poder obtener la respuesta, no puedes saber si tu escritura fue correcta o no. Y cuando recuperas la conexión, tampoco puedes saberlo, ya que no sabes cuál fue el recuento antes de incrementar. Este es un problema inherente con los sistemas que eligen la disponibilidad en lugar de la coherencia y el precio que paga por muchos de los otros beneficios.

Finalmente, el problema de eliminación rápida, incremento, eliminación es real y es algo que debe evitar. El problema es que la operación de incremento esencialmente resucitará la columna, y si estas operaciones se acercan lo suficiente entre sí, podrían obtener la misma marca de tiempo. Cassandra es estrictamente la última escritura-gana y determina la última en función de la marca de tiempo de la operación. Si dos operaciones tienen la misma marca de tiempo, la "mayor" gana, lo que significa la que ordena en un orden de bytes estricto. Es real, pero no me preocuparía demasiado a menos que esté haciendo escrituras y eliminaciones muy rápidas al mismo valor (que probablemente sea un error en su modelo de datos).

Aquí hay una buena guía para los aspectos internos de los contadores de Cassandra: http://www.datastax.com/wp-content/uploads/2011/07/cassandra_sf_counters.pdf


Para comprender las actualizaciones / incrementos, es decir, las operaciones de escritura, le sugeriré que lea el protocolo de Chisme utilizado por Cassandra para la comunicación. En Gossip, cada participante (nodo) mantiene su estado utilizando la tupla σ(K) = (V*N) donde σ(K) es el estado de la tecla K con el valor V y N como número de versión.

Para mantener la versión única de verdad para un paquete de datos, Gossip mantiene un mecanismo de conciliación, a saber, Precise & Scuttlebutt (actual). De acuerdo con la Scuttlebutt Reconciliation , antes de actualizar cualquier tupla, se comunican entre sí para comprobar quién tiene la versión más alta (el valor más reciente) de la clave. Quien tenga la versión más alta es responsable de la operación de escritura.

Para más información lea este article .