Acerca de pasar de Redis al clúster de Redis

Acerca de pasar de Redis al clúster de Redis

Al llegar a un producto que se ha estado desarrollando durante más de una década, no es nada sorprendente encontrar tecnologías obsoletas en él. Pero, ¿qué pasa si en seis meses tienes que mantener la carga 10 veces mayor y el coste de las caídas aumenta cientos de veces? En este caso, necesita un ingeniero de Highload genial. Pero ante la falta de una criada, me confiaron la solución del problema. En la primera parte del artículo, le contaré cómo pasamos de Redis al clúster de Redis, y en la segunda parte le daré consejos sobre cómo comenzar a usar el clúster y a qué prestar atención al usarlo.

Elección de tecnología

¿Es tan malo? Redis separados (redis independiente) en una configuración de 1 maestro y N esclavos? ¿Por qué la llamo tecnología obsoleta?

No, Redis no es tan malo... Sin embargo, hay algunas deficiencias que no se pueden ignorar.

  • Primero, Redis no admite mecanismos de recuperación ante desastres después de una falla maestra. Para solucionar este problema utilizamos una configuración con transferencia automática de VIP a un nuevo maestro, cambiando el rol de uno de los esclavos y cambiando el resto. Este mecanismo funcionó, pero no se puede considerar una solución confiable. En primer lugar, se producían falsas alarmas y, en segundo lugar, era desechable y, después de la operación, se requerían acciones manuales para cargar el resorte.

  • En segundo lugar, tener un solo maestro generaba el problema de la fragmentación. Tuvimos que crear varios clústeres independientes “1 maestro y N esclavos”, luego distribuir manualmente las bases de datos entre estas máquinas y esperar que mañana una de las bases de datos no se hinchara tanto como para tener que trasladarla a una instancia separada.

¿Cuáles son las opciones?

  • La solución más cara y rica es Redis-Enterprise. Esta es una solución en caja con soporte técnico completo. A pesar de que desde el punto de vista técnico parece ideal, no nos convenía por motivos ideológicos.
  • Clúster de Redis. De fábrica, hay soporte para conmutación por error y fragmentación de maestros. La interfaz casi no se diferencia de la versión normal. Parece prometedor, hablaremos de los peligros más adelante.
  • Tarantool, Memcache, Aerospike y otros. Todas estas herramientas hacen prácticamente lo mismo. Pero cada uno tiene sus propias deficiencias. Decidimos no poner todos nuestros huevos en la misma canasta. Usamos Memcache y Tarantool para otras tareas y, de cara al futuro, diré que en nuestra práctica surgieron más problemas con ellos.

Especificidad de uso

Echemos un vistazo a los problemas que hemos resuelto históricamente con Redis y qué funciones utilizamos:

  • Caché antes de solicitudes a servicios remotos como 2GIS | golang

    OBTENER SET MGET MSET "SELECCIONAR DB"

  • Caché antes de MYSQL | PHP

    GET SET MGET MSET SCAN "TECLA POR PATRÓN" "SELECCIONAR DB"

  • El almacenamiento principal para el servicio de trabajo con sesiones y coordenadas de conductores | golang

    GET SET MGET MSET "SELECCIONAR DB" "AÑADIR LLAVE GEO" "OBTENER LLAVE GEO" ESCANEAR

Como puede ver, no hay matemáticas superiores. ¿Cuál es entonces la dificultad? Veamos cada método por separado.

método
Descripción
Características del clúster Redis
Solución

Conseguir establecer
Tecla de escritura/lectura

MGET MSET
Escribir/leer múltiples claves
Las claves estarán en diferentes nodos. Las bibliotecas listas para usar pueden realizar múltiples operaciones solo dentro de un nodo
Reemplace MGET con una canalización de operaciones N GET

SELECCIONAR BD
Selecciona la base con la que trabajaremos
No soporta múltiples bases de datos
Pon todo en una base de datos. Agregar prefijos a las claves

ESCANEAR
Revisar todas las claves de la base de datos.
Como tenemos una base de datos, revisar todas las claves del clúster es demasiado costoso.
Mantenga una invariante dentro de una clave y realice un HSCAN en esta clave. O negarse por completo

GEO
Operaciones con geokey
La geokey no está fragmentada

CLAVE POR PATRÓN
Buscando una clave por patrón
Como tenemos una base de datos, buscaremos en todas las claves del clúster. Muy caro
Rechazar o mantener la invariante, como en el caso de SCAN

Redis vs Redis-clúster

¿Qué perdemos y qué ganamos al cambiar a un cluster?

  • Desventajas: perdemos la funcionalidad de varias bases de datos.
    • Si queremos almacenar datos lógicamente no relacionados en un grupo, tendremos que hacer muletas en forma de prefijos.
    • Perdemos todas las operaciones "básicas", como SCAN, DBSIZE, CLEAR DB, etc.
    • Las operaciones múltiples se han vuelto mucho más difíciles de implementar porque pueden requerir acceso a varios nodos.
  • ventajas:
    • Tolerancia a fallos en forma de conmutación por error maestra.
    • Fragmentación en el lado de Redis.
    • Transfiera datos entre nodos de forma atómica y sin tiempo de inactividad.
    • Agregue y redistribuya capacidad y cargas sin tiempo de inactividad.

Yo concluiría que si no es necesario proporcionar un alto nivel de tolerancia a fallos, entonces no vale la pena pasar a un clúster, porque puede ser una tarea no trivial. Pero si inicialmente elige entre una versión separada y una versión en clúster, entonces debería elegir una en clúster, ya que no es peor y, además, le aliviará algunos de los dolores de cabeza.

Preparándose para mudarse

Comencemos con los requisitos para mudarse:

  • Debería ser perfecto. Una parada completa del servicio durante 5 minutos no nos conviene.
  • Debe ser lo más seguro y gradual posible. Quiero tener cierto control sobre la situación. No queremos deshacernos de todo de una vez y rezar sobre el botón de retroceso.
  • Pérdida de datos mínima al moverse. Entendemos que será muy difícil moverse atómicamente, por lo que permitimos cierta desincronización entre los datos en Redis regular y agrupado.

Mantenimiento del cluster

Justo antes de la mudanza, deberíamos pensar si podemos admitir el clúster:

  • Gráficos. Usamos Prometheus y Grafana para graficar la carga de la CPU, el uso de la memoria, la cantidad de clientes, la cantidad de operaciones GET, SET, AUTH, etc.
  • Pericia. Imagínate que mañana tendrás un enorme cluster bajo tu responsabilidad. Si se rompe, nadie más que tú podrá arreglarlo. Si comienza a reducir la velocidad, todos correrán hacia ti. Si necesita agregar recursos o redistribuir la carga, regrese a usted. Para no ponerse gris a los 25, es recomendable prever estos casos y comprobar de antemano cómo se comportará la tecnología ante determinadas acciones. Hablemos de esto con más detalle en la sección "Experiencia".
  • Seguimiento y alertas. Cuando un clúster falla, usted quiere ser el primero en enterarse. Aquí nos limitamos a notificar que todos los nodos devuelven la misma información sobre el estado del clúster (sí, sucede de manera diferente). Y otros problemas pueden detectarse más rápidamente mediante alertas de los servicios al cliente de Redis.

En movimiento

Cómo nos moveremos:

  • En primer lugar, debe preparar una biblioteca para trabajar con el clúster. Tomamos go-redis como base para la versión Go y lo cambiamos un poco para adaptarnos a nosotros. Implementamos métodos múltiples a través de canalizaciones y también corregimos ligeramente las reglas para solicitudes repetidas. La versión PHP tuvo más problemas, pero finalmente nos decidimos por php-redis. Recientemente introdujeron soporte para clústeres y, en nuestra opinión, se ve bien.
  • A continuación, debe implementar el clúster. Esto se hace literalmente en dos comandos basados ​​en el archivo de configuración. Discutiremos la configuración con más detalle a continuación.
  • Para movimientos graduales utilizamos el modo seco. Dado que tenemos dos versiones de la biblioteca con la misma interfaz (una para la versión normal y la otra para el clúster), no cuesta nada crear un contenedor que funcione con una versión separada y en paralelo duplique todas las solicitudes al clúster. compare respuestas y escriba discrepancias en los registros (en nuestro caso en NewRelic). Por lo tanto, incluso si la versión del clúster falla durante la implementación, nuestra producción no se verá afectada.
  • Después de implementar el clúster en modo seco, podemos observar con seguridad el gráfico de discrepancias de respuesta. Si la tasa de error avanza lenta pero seguramente hacia una pequeña constante, entonces todo está bien. ¿Por qué todavía hay discrepancias? Debido a que la grabación en una versión separada ocurre un poco antes que en el grupo y debido al microlag, los datos pueden divergir. Todo lo que queda es mirar los registros de discrepancia, y si todos se explican por la no atomicidad del registro, entonces podemos seguir adelante.
  • Ahora puedes cambiar el modo seco en la dirección opuesta. Escribiremos y leeremos desde el clúster y lo duplicaremos en una versión separada. ¿Para qué? Durante la próxima semana me gustaría observar el trabajo del grupo. Si de repente resulta que hay problemas durante la carga máxima, o no tomamos algo en cuenta, siempre tenemos una reversión de emergencia al código antiguo y a los datos actuales gracias al modo seco.
  • Todo lo que queda es desactivar el modo seco y desmontar la versión separada.

Экспертиза

Primero, brevemente sobre el diseño del cluster.

En primer lugar, Redis es un almacén de valores clave. Se utilizan cadenas arbitrarias como claves. Se pueden utilizar como valores números, cadenas y estructuras completas. Hay muchos de estos últimos, pero para comprender la estructura general esto no es importante para nosotros.
El siguiente nivel de abstracción después de las claves son las ranuras (SLOTS). Cada clave pertenece a una de las 16 ranuras. Puede haber cualquier cantidad de claves dentro de cada ranura. Por tanto, todas las claves se dividen en 383 conjuntos disjuntos.
Acerca de pasar de Redis al clúster de Redis

A continuación, debe haber N nodos maestros en el clúster. Se puede considerar a cada nodo como una instancia de Redis independiente que sabe todo sobre los demás nodos dentro del clúster. Cada nodo maestro contiene una cantidad de ranuras. Cada ranura pertenece a un solo nodo maestro. Todas las ranuras deben distribuirse entre los nodos. Si algunas ranuras no están asignadas, las claves almacenadas en ellas serán inaccesibles. Tiene sentido ejecutar cada nodo maestro en una máquina lógica o física separada. También vale la pena recordar que cada nodo solo se ejecuta en un núcleo, y si desea ejecutar varias instancias de Redis en la misma máquina lógica, asegúrese de que se ejecuten en diferentes núcleos (no hemos probado esto, pero en teoría debería funcionar). . Básicamente, los nodos maestros proporcionan fragmentación regular y más nodos maestros permiten escalar las solicitudes de escritura y lectura.

Una vez que todas las claves se distribuyen entre las ranuras y las ranuras se distribuyen entre los nodos maestros, se puede agregar una cantidad arbitraria de nodos esclavos a cada nodo maestro. Dentro de cada enlace maestro-esclavo, funcionará la replicación normal. Se necesitan esclavos para escalar las solicitudes de lectura y para la conmutación por error en caso de falla del maestro.
Acerca de pasar de Redis al clúster de Redis

Ahora hablemos de operaciones que sería mejor poder realizar.

Accederemos al sistema vía Redis-CLI. Dado que Redis no tiene un único punto de entrada, puede realizar las siguientes operaciones en cualquiera de los nodos. En cada punto llamo la atención por separado sobre la posibilidad de realizar la operación bajo carga.

  • Lo primero y más importante que necesitamos es el funcionamiento de los nodos del clúster. Devuelve el estado del clúster, muestra una lista de nodos, sus funciones, distribución de espacios, etc. Se puede obtener más información utilizando la información del clúster y las ranuras del clúster.
  • Sería bueno poder agregar y eliminar nodos. Para ello existen operaciones de encuentro y olvido de clústeres. Tenga en cuenta que el olvido del clúster debe aplicarse a CADA nodo, tanto maestros como réplicas. Y la reunión del clúster solo debe convocarse en un nodo. Esta diferencia puede resultar desconcertante, por lo que es mejor conocerla antes de poner en marcha su clúster. Agregar un nodo se realiza de forma segura en la batalla y no afecta el funcionamiento del clúster de ninguna manera (lo cual es lógico). Si va a eliminar un nodo del clúster, debe asegurarse de que no queden ranuras en él (de lo contrario, corre el riesgo de perder el acceso a todas las claves de este nodo). Además, no elimine un maestro que tenga esclavos; de lo contrario, se realizará una votación innecesaria para un nuevo maestro. Si los nodos ya no tienen ranuras, entonces este es un pequeño problema, pero ¿por qué necesitamos opciones adicionales si podemos eliminar los esclavos primero?
  • Si necesita intercambiar por la fuerza las posiciones maestra y esclava, entonces el comando de conmutación por error del clúster será suficiente. Al convocarlo en batalla, debes comprender que el maestro no estará disponible durante la operación. Normalmente el cambio se produce en menos de un segundo, pero no es atómico. Puede esperar que algunas solicitudes al maestro fallen durante este tiempo.
  • Antes de eliminar un nodo del clúster, no deben quedar ranuras en él. Es mejor redistribuirlos usando el comando cluster reshard. Las ranuras se transferirán de un maestro a otro. Toda la operación puede tardar varios minutos, depende del volumen de datos que se transfieran, pero el proceso de transferencia es seguro y no afecta el funcionamiento del clúster de ninguna manera. De este modo, todos los datos se pueden transferir de un nodo a otro directamente bajo carga y sin preocuparse por su disponibilidad. Sin embargo, también hay sutilezas. En primer lugar, la transferencia de datos está asociada con una determinada carga en los nodos destinatario y emisor. Si el nodo destinatario ya está muy cargado en el procesador, entonces no debe cargarlo para recibir nuevos datos. En segundo lugar, tan pronto como no quede ni una sola ranura en el maestro emisor, todos sus esclavos irán inmediatamente al maestro al que se transfirieron estas ranuras. Y el problema es que todos estos esclavos querrán sincronizar datos a la vez. Y tendrás suerte si se trata de una sincronización parcial en lugar de completa. Tenga esto en cuenta y combine las operaciones de transferir ranuras y deshabilitar/transferir esclavos. O esperar tener un margen de seguridad suficiente.
  • ¿Qué debe hacer si, durante la transferencia, descubre que ha perdido sus espacios en alguna parte? Espero que este problema no le afecte, pero si lo hace, existe una operación de reparación del clúster. Como mínimo, distribuirá las ranuras entre los nodos en orden aleatorio. Recomiendo comprobar su funcionamiento eliminando primero del cluster el nodo con slots distribuidos. Dado que los datos en espacios no asignados ya no están disponibles, es demasiado tarde para preocuparse por problemas con la disponibilidad de estos espacios. A su vez, la operación no afectará a las franjas horarias distribuidas.
  • Otra operación útil es monitorear. Le permite ver en tiempo real la lista completa de solicitudes que van al nodo. Además, puedes explorarlo y averiguar si existe el tráfico necesario.

También vale la pena mencionar el procedimiento de conmutación por error del maestro. En definitiva, existe y, en mi opinión, funciona muy bien. Sin embargo, no crea que si desconecta el cable de alimentación de una máquina con un nodo maestro, Redis cambiará inmediatamente y los clientes no notarán la pérdida. En mi práctica, el cambio se produce en unos segundos. Durante este tiempo, algunos de los datos no estarán disponibles: se detecta la indisponibilidad del maestro, los nodos votan por uno nuevo, los esclavos se cambian, los datos se sincronizan. La mejor manera de asegurarse de que el plan funciona es realizar ejercicios locales. Levante el clúster de su computadora portátil, déle una carga mínima, simule una falla (por ejemplo, bloqueando los puertos) y evalúe la velocidad de conmutación. En mi opinión, sólo después de jugar de esta manera durante uno o dos días podrás tener confianza en el funcionamiento de la tecnología. Bueno, o esperar que el software que utiliza la mitad de Internet probablemente funcione.

Configuración

A menudo, la configuración es lo primero que necesitas para empezar a trabajar con la herramienta y, cuando todo funciona, ni siquiera quieres tocar la configuración. Se necesita algo de esfuerzo para obligarse a volver a la configuración y revisarla con atención. En mi memoria tuvimos al menos dos fallos graves por falta de atención a la configuración. Preste especial atención a los siguientes puntos:

  • tiempo de espera 0
    Tiempo después del cual se cierran las conexiones inactivas (en segundos). 0 - no cerrar
    No todas nuestras bibliotecas pudieron cerrar las conexiones correctamente. Al deshabilitar esta configuración, corremos el riesgo de alcanzar el límite en la cantidad de clientes. Por otro lado, si existe un problema de este tipo, la terminación automática de las conexiones perdidas lo enmascarará y es posible que no nos demos cuenta. Además, no debe habilitar esta configuración cuando utilice conexiones persistentes.
  • Guardar xy y agregar solo sí
    Guardar una instantánea RDB.
    Discutiremos los problemas de RDB/AOF en detalle a continuación.
  • detener-escritura-en-bgsave-error no y esclavo-servir-datos-obsoletos sí
    Si está habilitado, si la instantánea RDB se rompe, el maestro dejará de aceptar solicitudes de cambio. Si se pierde la conexión con el maestro, el esclavo puede continuar respondiendo a las solicitudes (sí). O dejará de responder (no)
    No estamos contentos con la situación en la que Redis se convierte en una calabaza.
  • repl-ping-esclavo-periodo 5
    Pasado este periodo de tiempo, comenzaremos a preocuparnos de que el maestro se haya averiado y sea el momento de realizar el procedimiento de conmutación por error.
    Tendrá que encontrar manualmente un equilibrio entre los falsos positivos y la activación de una conmutación por error. En nuestra práctica esto es 5 segundos.
  • repl-backlog-size 1024mb y epl-backlog-ttl 0
    Podemos almacenar exactamente esta cantidad de datos en un búfer para una réplica fallida. Si el búfer se agota, tendrás que sincronizar completamente.
    La práctica sugiere que es mejor establecer un valor más alto. Hay muchas razones por las que una réplica puede empezar a retrasarse. Si se retrasa, lo más probable es que su maestro ya esté luchando por hacer frente, y la sincronización completa será el colmo.
  • clientes máximos 10000
    Número máximo de clientes únicos.
    Según nuestra experiencia, es mejor establecer un valor más alto. Redis maneja bien conexiones de 10k. Solo asegúrese de que haya suficientes enchufes en el sistema.
  • política-maxmemory-ttl volátil
    La regla por la cual las claves se eliminan cuando se alcanza el límite de memoria disponible.
    Lo importante aquí no es la norma en sí, sino entender cómo sucederá. Se puede elogiar a Redis por su capacidad para funcionar normalmente cuando se alcanza el límite de memoria.

Problemas RDB y AOF

Aunque Redis almacena toda la información en la RAM, también existe un mecanismo para guardar datos en el disco. Más precisamente, tres mecanismos:

  • Instantánea RDB: una instantánea completa de todos los datos. Configúrelo usando la configuración GUARDAR XY y dice "Guardar una instantánea completa de todos los datos cada X segundos si al menos las claves Y han cambiado".
  • Archivo de solo agregar: una lista de operaciones en el orden en que se realizan. Agrega nuevas operaciones entrantes al archivo cada X segundos o cada Y operaciones.
  • RDB y AOF son una combinación de los dos anteriores.

Todos los métodos tienen sus ventajas y desventajas, no las enumeraré todas, solo llamaré la atención sobre puntos que, en mi opinión, no son obvios.

Primero, para guardar una instantánea de RDB es necesario llamar a FORK. Si hay muchos datos, esto puede bloquear todo Redis durante un período de unos pocos milisegundos a un segundo. Además, el sistema necesita asignar memoria para dicha instantánea, lo que lleva a la necesidad de mantener un doble suministro de RAM en la máquina lógica: si se asignan 8 GB para Redis, entonces deberían estar disponibles 16 GB en la máquina virtual con él.

En segundo lugar, existen problemas con la sincronización parcial. En el modo AOF, cuando se vuelve a conectar el esclavo, en lugar de una sincronización parcial, se puede realizar una sincronización completa. Por qué sucede esto, no lo pude entender. Pero vale la pena recordar esto.

Estos dos puntos ya nos hacen pensar si realmente necesitamos estos datos en el disco si ya todo está duplicado por los esclavos. Los datos sólo se pueden perder si todos los esclavos fallan, y esto es un problema de nivel de "incendio en el DC". Como compromiso, puede proponer guardar datos solo en los esclavos, pero en este caso debe asegurarse de que estos esclavos nunca se conviertan en maestros durante la recuperación ante desastres (para esto hay una configuración de prioridad de esclavo en su configuración). Por nuestra parte, en cada caso concreto pensamos si es necesario guardar datos en el disco, y la mayoría de las veces la respuesta es "no".

Conclusión

En conclusión, espero haber podido dar una idea general de cómo funciona Redis-cluster para aquellos que no han oído hablar de él en absoluto, y también llamar la atención sobre algunos puntos no obvios para aquellos que lo han estado usando. por mucho tiempo.
Gracias por tu tiempo y, como siempre, los comentarios sobre el tema son bienvenidos.

Fuente: habr.com

Añadir un comentario