Cassandra proporciona una consistencia ajustable, que incluye la capacidad de lograr una consistencia fuerte al especificar niveles de consistencia suficientemente altos.
Sin embargo, una consistencia sólida no es suficiente para evitar las condiciones de competencia en los casos en que los clientes necesitan leer y luego escribir datos.
Vamos explicar esto con un ejemplo, supongamos que tenemos una tabla Cliente. Imagine que estamos creando un cliente y que desea administrar los registros de usuarios como parte de una aplicación de administración de cuentas. Al crear una nueva cuenta de usuario, nos gustaría
asegúrarnos de que el registro de usuario no exista, para no sobrescribir involuntariamente los datos de usuario existentes. Así que hacemos una lectura para ver si el registro existe primero, y luego solo realizamos la creación si el registro no existe. El comportamiento que buscamos se denomina consistencia linealizable, lo que significa que nos gustaría garantizar que ningún otro cliente pueda interponerse entre nuestras consultas de lectura y escritura con su propia modificación. Desde la versión 2.0, Cassandra admite un mecanismo de transacción ligero (o "LWT") que proporciona una consistencia linealizable.
La implementación de LWT de Cassandra se basa en Paxos. Paxos es un algoritmo de consenso que permite que los nodos pares distribuidos se pongan de acuerdo sobre una propuesta, sin necesidad de un maestro para coordinar una transacción. Paxos y otros algoritmos de consenso surgieron como alternativas a los enfoques tradicionales basados en el compromiso de dos fases para las transacciones distribuidas.
El algoritmo básico de Paxos consta de dos etapas: preparar / prometer y proponer / aceptar. Para modificar los datos, un nodo coordinador puede proponer un nuevo valor a los nodos de réplica, asumiendo el rol de líder. Otros nodos pueden actuar como líderes simultáneamente para otras modificaciones. Cada nodo de réplica verifica la propuesta, y si la propuesta es la última que ha visto, promete no aceptar las propuestas asociadas con las propuestas anteriores. Cada nodo de réplica también devuelve la última propuesta que recibió que aún está en progreso. Si la propuesta es aprobada por la mayoría de las réplicas, el líder confirma la propuesta, pero con la advertencia de que primero debe cometer cualquier propuesta en curso que haya precedido a su propia propuesta.
La implementación de Cassandra amplía el algoritmo básico de Paxos para admitir la semántica de lectura antes de escritura deseada (también conocida como "comprobar y establecer"), y permitir que el estado se reinicie entre transacciones. Lo hace insertando dos fases adicionales en el algoritmo, para que funcione de la siguiente manera:
- Preparar / prometer
- Leer / Resultados
- Proponer / Aceptar
- Cometer / Ack
Por lo tanto, una transacción exitosa requiere cuatro viajes de ida y vuelta entre el nodo coordinador y las réplicas. Esto es más costoso que una escritura regular, por lo que debe pensar detenidamente sobre su caso de uso antes de usar LWT.
Las transacciones ligeras de Cassandra están limitadas a una sola partición. Internamente, Cassandra almacena un estado Paxos para cada partición. Esto asegura que las transacciones en diferentes particiones no puedan interferir entre sí.
Puede encontrar la implementación de Cassandra del algoritmo Paxos en el paquete org.apache.cassandra.service.paxos.