Categorías
Techies

El problema de las particiones en Cassandra

Quizás este sea uno de los problemas principales cuando se define el modelo de datos en Cassandra. En un cluster, algunos nodos no paran de crecer y otros quedan prácticamente sin uso.

Esta misma semana contactaron conmigo para pedirme consejo de un proyecto en el que usaban Cassandra. Llevaban un par de años con el proyecto y veían como unos nodos se les llenaban y no paraban de agregar gigas de almacenamiento. Mientras tanto otros nodos se mantenían apenas sin uso desde inicio.

Lo primero que viene a la cabeza es, problema de particiones. Os cuento.

Os voy a poner unos ejemplos inventados porque no puedo contar nada del proyecto. haré un simil.

Imaginaos sensores de tráfico en los que cada vez que pasa un coche por un punto, guarda la fecha-hora. Imaginaos que esto se hace en todas las ciudades y pueblos de España. Por lo que podemos tener millones de lecturas en Madrid, y unas pocas decenas de lecturas en mi pueblo.

La tabla principal, y la que más ocupaba, tenía como clave de partición el código de ciudad, y la fechaHora y localización del sensor como clustering order.

  • Ciudad – Clave Partición
  • FechaHora (detalle en milisegundos) – C Order
  • LocalizacionSensor – C Order

Recordemos la fórmula para calcular las particiones teniendo en cuenta que se recomienda que Ncells<1M:

Ncells=Nrow*(NCols-Npk-Nstatic)+Nstatic
Ncells=Nrow*(3-1-0)+0
Ncells=Nrow*2
1M=Nrow*2
Nrow=500000 registros.

Es decir, por cada ciudad puedo tener más de 500000 registros. En nuestro caso, previo estudio, se vio que hay ciudades con hasta 10 Millones de registros.

Como la clave de partición está por ciudad, hay un nodo petadísimo donde se guarda toda la información de Madrid, y tendré otro nodo como nuevo con la información de mi pueblo. ¿Veis lo mal que seleccionaron la clave de partición?

Particionar una tabla sin cambiar el chip

La pregunta sería, ¿entonces como lo hacemos? Pues depende del proyecto.

En este caso las consultas se realizaban desde un BI que ejecutaba cada dia una sola vez captando las lecturas del dia por cada ciudad. Éste realizaba una lectura del ultimo dia para realizar distintas agregaciones.

Por lo tanto nuestra prioridad es escribir en todos los nodos de la forma más igualitaria posible. Vamos a probar añadiendo el día y la hora a la clave de particion. La estructura elegida:

  • Ciudad – Clave Particion
  • DiaHora (YYYYMMDDHH) – Clave Partición
  • FechaHora (detalle en milisegundos) – C Order
  • LocalizacionSensor – C Order

Ncells=Nrow*(NCols-Npk-Nstatic)+Nstatic
Ncells=Nrow*(4-2-0)+0
Ncells=Nrow*2
1M=Nrow*2
Nrow=500000 registros.

Es decir, por cada ciudad y hora puedo tener más de 500000 registros. En nuestro caso, previo estudio, se vio que hay ciudades con hasta 10 Millones de registros al día, esto es 417000 registros a la hora de media con algún pico superando el millón. Por lo que esta estructura fue la elegida.

Además, a cada registro se le asignó un TTL de una semana. ¡En varios años habían hecho limpieza de registros antiguos 5 o 6 veces solo!

Antes se escribían en X particiones, correspondiendo X al número de ciudades. Independientemente del día cada ciudad tenia asignado un nodo. Ahora se distribuyen las escrituras dependiendo también del día.

La lectura se hace en tantas particiones como ciudades existen, ya que nos limitamos a leer un solo día.

Y lo más importante, ahora el volumen de datos además de reducirse en general, se distribuye de forma más equitativa por todo el cluster.

¿Moraleja? Elije bien tu clave de partición y cambia la mentalidad de base de datos relacional. NoSQL es otro mundo.

Recordemos:

  • Las claves primarias, las claves de agrupación y el orden de agrupación no se pueden cambiar después de crear una tabla. Así que piensa bién a la hora de crear una tabla si no quieres tener la tarea de tener que crear una tabla y mover datos antiguos a una nueva tabla.
  • Una particion para que sea eficiente debe tener menos de 1 millon de registros.