Casandra. Cómo no morir si solo conoces Oracle

Hola Habr.

Mi nombre es Misha Butrimov, me gustaría contarles un poco sobre Cassandra. Mi historia será útil para aquellos que nunca se han encontrado con bases de datos NoSQL: tiene muchas características de implementación y dificultades que deben conocer. Y si no ha visto nada más que Oracle o cualquier otra base de datos relacional, estas cosas le salvarán la vida.

¿Qué tiene de bueno Casandra? Es una base de datos NoSQL diseñada sin un único punto de falla y que escala bien. Si necesita agregar un par de terabytes para alguna base de datos, simplemente agregue nodos al anillo. ¿Expandirlo a otro centro de datos? Agregue nodos al clúster. ¿Aumentar el RPS procesado? Agregue nodos al clúster. También funciona en la dirección opuesta.

Casandra. Cómo no morir si solo conoces Oracle

¿En qué más es buena? Se trata de manejar muchas solicitudes. ¿Pero cuánto es mucho? 10, 20, 30, 40 mil solicitudes por segundo no es mucho. También 100 solicitudes de grabación por segundo. Hay empresas que dicen que mantienen 2 millones de solicitudes por segundo. Probablemente tendrán que creerlo.

Y, en principio, Cassandra tiene una gran diferencia con los datos relacionales: no se parece en nada a ellos. Y es muy importante recordar esto.

No todo lo que parece igual funciona igual

Una vez un colega se acercó a mí y me preguntó: “Aquí hay un lenguaje de consulta CQL Cassandra y tiene una declaración de selección, tiene dónde, tiene y. Escribo cartas y no funciona. ¿Por qué?". Tratar a Cassandra como una base de datos relacional es la manera perfecta de cometer un suicidio violento. Y no lo estoy promocionando, está prohibido en Rusia. Simplemente diseñarás algo mal.

Por ejemplo, un cliente se acerca a nosotros y nos dice: “Creemos una base de datos para series de televisión o una base de datos para un directorio de recetas. Tendremos platos de comida allí o una lista de series de televisión y actores”. Decimos alegremente: "¡Vamos!" Simplemente envíe dos bytes, un par de señales y listo, todo funcionará de manera muy rápida y confiable. Y todo va bien hasta que vienen los clientes y dicen que las amas de casa también están solucionando el problema contrario: tienen una lista de productos y quieren saber qué plato quieren cocinar. Estás muerto.

Esto se debe a que Cassandra es una base de datos híbrida: proporciona simultáneamente un valor clave y almacena datos en columnas anchas. En Java o Kotlin, podría describirse así:

Map<RowKey, SortedMap<ColumnKey, ColumnValue>>

Es decir, un mapa que también contiene un mapa ordenado. La primera clave de este mapa es la clave de Fila o clave de Partición: la clave de partición. La segunda clave, que es la clave para un mapa ya ordenado, es la clave de agrupación.

Para ilustrar la distribución de la base de datos, dibujemos tres nodos. Ahora necesitas entender cómo descomponer los datos en nodos. Porque si juntamos todo en uno (por cierto, puede haber mil, dos mil, cinco, tantos como quieras), no se trata realmente de distribución. Por lo tanto, necesitamos una función matemática que devuelva un número. Sólo un número, un int largo que estará dentro de algún rango. Y tendremos un nodo responsable de un rango, el segundo del segundo, el enésimo del enésimo.

Casandra. Cómo no morir si solo conoces Oracle

Este número se toma mediante una función hash, que se aplica a lo que llamamos clave de partición. Esta es la columna que se especifica en la directiva de clave primaria y esta es la columna que será la primera y más básica clave del mapa. Determina qué nodo recibirá qué datos. Se crea una tabla en Cassandra con casi la misma sintaxis que en SQL:

CREATE TABLE users (
	user_id uu id,
	name text,
	year int,
	salary float,
	PRIMARY KEY(user_id)

)

La clave principal en este caso consta de una columna y también es la clave de partición.

¿Cómo se desempeñarán nuestros usuarios? Algunos irán a un nodo, otros a otro y otros a un tercero. El resultado es una tabla hash ordinaria, también conocida como mapa, también conocida como diccionario en Python, o una estructura de valor clave simple desde la cual podemos leer todos los valores, leer y escribir por clave.

Casandra. Cómo no morir si solo conoces Oracle

Seleccione: cuándo permitir el filtrado se convierte en análisis completo o qué no hacer

Escribamos una declaración selecta: select * from users where, userid = . Resulta como en Oracle: escribimos select, especificamos las condiciones y todo funciona, los usuarios lo entienden. Pero si selecciona, por ejemplo, un usuario con un año de nacimiento determinado, Cassandra se queja de que no puede cumplir con la solicitud. Porque ella no sabe nada sobre cómo distribuimos los datos sobre el año de nacimiento: solo tiene una columna indicada como clave. Luego dice: “Está bien, todavía puedo cumplir con esta solicitud. Añadir permitir filtrado." Agregamos la directiva, todo funciona. Y en ese momento sucede algo terrible.

Cuando ejecutamos datos de prueba, todo está bien. Y cuando ejecutas una consulta en producción, donde tenemos, por ejemplo, 4 millones de registros, entonces no todo nos va muy bien. Porque permitir el filtrado es una directiva que permite a Cassandra recopilar todos los datos de esta tabla de todos los nodos, todos los centros de datos (si hay muchos de ellos en este clúster) y solo entonces filtrarlos. Este es un análogo de Full Scan y casi nadie está encantado con él.

Si solo necesitáramos usuarios por ID, estaríamos bien con esto. Pero a veces necesitamos escribir otras consultas e imponer otras restricciones a la selección. Por eso recordamos: todo esto es un mapa que tiene una clave de partición, pero dentro hay un mapa ordenado.

Y también tiene una clave, que llamamos Clave de Agrupación. Esta clave, que, a su vez, consta de las columnas que seleccionamos, con la ayuda de las cuales Cassandra comprende cómo se ordenan físicamente sus datos y se ubicarán en cada nodo. Es decir, para algunas claves de partición, la clave de agrupación le dirá exactamente cómo insertar los datos en este árbol y qué lugar ocuparán allí.

Esto es realmente un árbol, allí simplemente se llama un comparador, al que le pasamos un determinado conjunto de columnas en forma de objeto, y también se especifica como una lista de columnas.

CREATE TABLE users_by_year_salary_id (
	user_id uuid,
	name text,
	year int,
	salary float,
	PRIMARY KEY((year), salary, user_id)

Preste atención a la directiva de clave primaria; su primer argumento (en nuestro caso, el año) es siempre la clave de partición. Puede constar de una o más columnas, no importa. Si hay varias columnas, es necesario eliminarlas entre paréntesis nuevamente para que el preprocesador del lenguaje comprenda que esta es la clave principal y, detrás de ella, todas las demás columnas son la clave de agrupación. En este caso, se transmitirán en el comparador en el orden en que aparecen. Es decir, la primera columna es más significativa, la segunda es menos significativa y así sucesivamente. La forma en que escribimos, por ejemplo, es igual a los campos para las clases de datos: enumeramos los campos y para ellos escribimos cuáles son más grandes y cuáles son más pequeños. En Cassandra, estos son, relativamente hablando, los campos de la clase de datos a los que se aplicarán los iguales escritos para ella.

Establecemos clasificación e imponemos restricciones.

Debe recordar que el orden de clasificación (descendente, ascendente, lo que sea) se establece en el mismo momento en que se crea la clave y no se puede cambiar más adelante. Determina físicamente cómo se ordenarán los datos y cómo se almacenarán. Si necesita cambiar la clave de agrupación o el orden de clasificación, deberá crear una nueva tabla y transferir datos a ella. Esto no funcionará con uno existente.

Casandra. Cómo no morir si solo conoces Oracle

Llenamos nuestra tabla con usuarios y vimos que caían en un anillo, primero por año de nacimiento y luego dentro de cada nodo por salario e ID de usuario. Ahora podemos seleccionar imponiendo restricciones.

Nuestro de trabajo aparece de nuevo. where, and, obtenemos usuarios y todo vuelve a estar bien. Pero si intentamos usar solo una parte de la clave de agrupamiento, y una menos significativa, entonces Cassandra se quejará inmediatamente de que no puede encontrar el lugar en nuestro mapa donde este objeto, que tiene estos campos para el comparador nulo, y éste que acaba de establecer, - donde yace. Tendré que recuperar todos los datos de este nodo nuevamente y filtrarlos. Y esto es un análogo de Full Scan dentro de un nodo, esto es malo.

En cualquier situación poco clara, cree una nueva tabla.

Si queremos poder dirigirnos a los usuarios por ID, edad o salario, ¿qué debemos hacer? Nada. Solo usa dos tablas. Si necesita llegar a los usuarios de tres formas diferentes, habrá tres tablas. Atrás quedaron los días en los que ahorrábamos espacio en el tornillo. Este es el recurso más barato. Cuesta mucho menos que el tiempo de respuesta, lo que puede resultar perjudicial para el usuario. Es mucho más agradable para el usuario recibir algo en un segundo que en 10 minutos.

Cambiamos espacio innecesario y datos desnormalizados por la capacidad de escalar bien y operar de manera confiable. Después de todo, de hecho, un clúster que consta de tres centros de datos, cada uno de los cuales tiene cinco nodos, con un nivel aceptable de conservación de datos (cuando no se pierde nada), es capaz de sobrevivir completamente a la muerte de un centro de datos. Y dos nodos más en cada uno de los dos restantes. Y sólo después de esto comienzan los problemas. Esta es una redundancia bastante buena, vale la pena un par de unidades SSD y procesadores adicionales. Por lo tanto, para utilizar Cassandra, que nunca es SQL, en el que no hay relaciones ni claves externas, es necesario conocer reglas simples.

Diseñamos todo según su petición. Lo principal no son los datos, sino cómo va a trabajar la aplicación con ellos. Si necesita recibir diferentes datos de diferentes maneras o los mismos datos de diferentes maneras, debemos colocarlos de una manera que sea conveniente para la aplicación. De lo contrario fallaremos en Full Scan y Cassandra no nos dará ninguna ventaja.

La desnormalización de datos es la norma. Nos olvidamos de las formas normales, ya no tenemos bases de datos relacionales. Si dejamos algo 100 veces, se tumbará 100 veces. Sigue siendo más barato que parar.

Seleccionamos las claves a particionar para que se distribuyan con normalidad. No queremos que el hash de nuestras claves caiga dentro de un rango estrecho. Es decir, el año de nacimiento del ejemplo anterior es un mal ejemplo. Más precisamente, es bueno si nuestros usuarios están distribuidos normalmente por año de nacimiento, y malo si estamos hablando de estudiantes de quinto grado: la partición allí no será muy buena.

La clasificación se selecciona una vez en la etapa de creación de la clave de agrupación. Si es necesario cambiarlo, tendremos que actualizar nuestra tabla con una clave diferente.

Y lo más importante: si necesitamos recuperar los mismos datos de 100 formas diferentes, entonces tendremos 100 tablas diferentes.

Fuente: habr.com

Añadir un comentario