En su charla, Andrey Borodin te contará cómo tuvieron en cuenta la experiencia del escalado de PgBouncer a la hora de diseñar un pooler de conexiones.
Vídeo:
¡Hola a todos! Mi nombre es Andrew.
En Yandex, desarrollo bases de datos de código abierto. Y hoy tenemos un tema sobre conexiones de agrupadores de conexiones.
Si sabes cómo llamar al pool de conexiones en ruso, dímelo. Realmente quiero encontrar un buen término técnico que deba establecerse en la literatura técnica.
El tema es bastante complicado, porque en muchas bases de datos el pooler de conexiones está integrado y ni siquiera necesitas saberlo. Algunas configuraciones, por supuesto, están en todas partes, pero en Postgres esto no funciona. Y en paralelo (en HighLoad++ 2019) hay un informe de Nikolai Samokhvalov sobre la configuración de consultas en Postgres. Y entiendo que han venido personas que ya han configurado las solicitudes perfectamente, y estas son personas que se enfrentan a problemas más raros del sistema relacionados con la red y la utilización de recursos. Y en algunos lugares puede resultar bastante difícil en el sentido de que los problemas no son obvios.
Yandex tiene Postgres. Muchos servicios de Yandex se encuentran en Yandex.Cloud. Y tenemos varios petabytes de datos que generan al menos un millón de solicitudes por segundo en Postgres.
Y proporcionamos un clúster bastante típico para todos los servicios: este es el nodo principal principal del nodo, las dos réplicas habituales (sincrónica y asíncrona), copia de seguridad y escalado de solicitudes de lectura en la réplica.
Cada nodo del clúster es Postgres, en el que, además de Postgres y los sistemas de monitoreo, también está instalado un agrupador de conexiones. El pooler de conexiones se utiliza para cercar y para su propósito principal.
¿Cuál es el objetivo principal de un agrupador de conexiones?
Postgres adopta un modelo de proceso para trabajar con una base de datos. Esto significa que una conexión es un proceso, un backend de Postgres. Y hay muchos cachés diferentes en este backend, que son bastante costosos de hacer diferentes para diferentes conexiones.
Además, hay una matriz en el código de Postgres llamada procArray. Contiene datos básicos sobre conexiones de red. Y casi todos los algoritmos de procesamiento de procArray tienen una complejidad lineal, se ejecutan en toda la gama de conexiones de red. Es un ciclo bastante rápido, pero con más conexiones de red entrantes, las cosas se vuelven un poco más caras. Y cuando las cosas se vuelven un poco más caras, terminas pagando un precio muy alto por una gran cantidad de conexiones de red.
Hay 3 enfoques posibles:
- Del lado de la aplicación.
- Del lado de la base de datos.
- Y entre, es decir, todas las combinaciones posibles.
Desafortunadamente, el pooler integrado está actualmente en desarrollo. Los amigos de PostgreSQL Professional hacen esto principalmente. Cuándo aparecerá es difícil de predecir. Y de hecho, tenemos dos soluciones para la elección de arquitecto. Estos son el grupo del lado de la aplicación y el grupo de proxy.
El grupo del lado de la aplicación es la forma más sencilla. Y casi todos los controladores de cliente le proporcionan una manera: representar millones de sus conexiones en el código como algunas docenas de conexiones a la base de datos.
Existe un problema con el hecho de que, en cierto punto, desea escalar el backend y desea implementarlo en muchas máquinas virtuales.
Entonces todavía te das cuenta de que tienes varias zonas de disponibilidad más, varios centros de datos. Y el enfoque de agrupación del lado del cliente genera grandes cifras. Los grandes tienen unas 10 conexiones. Esta es una ventaja que puede funcionar bien.
Si hablamos de agrupadores de proxy, entonces hay dos agrupadores que pueden hacer muchas cosas. No son sólo poolers. Son poolers + funcionalidades más interesantes. Este
Pero, lamentablemente, no todo el mundo necesita esta funcionalidad adicional. Y esto lleva al hecho de que los poolers solo admiten la agrupación de sesiones, es decir, un cliente entrante y un cliente saliente a la base de datos.
Esto no es muy adecuado para nuestras tareas, por lo que utilizamos PgBouncer, que implementa la agrupación de transacciones, es decir, las conexiones del servidor se asignan a las conexiones del cliente solo durante la duración de la transacción.
Y en nuestra carga, es verdad. Pero hay varios problemas..
Los problemas comienzan cuando quieres diagnosticar una sesión, porque todas las conexiones entrantes son locales. Todos vinieron con loopback y de alguna manera resulta difícil rastrear la sesión.
Por supuesto que puedes usar application_name_add_host. Esta es la forma secundaria de Bouncer de agregar una dirección IP al nombre_aplicación. Pero el nombre_aplicación lo establece una conexión adicional.
En este gráfico, donde la línea amarilla son las solicitudes reales y donde la línea azul son las solicitudes que llegan a la base de datos. Y esta diferencia es precisamente la configuración de nombre_aplicación, que sólo es necesaria para el seguimiento, pero no es gratuita en absoluto.
Además, Bouncer no puede limitar un grupo, es decir, el número de conexiones de bases de datos por usuario, por base de datos.
¿A qué conduce esto? Tienes un servicio cargado escrito en C++ y en algún lugar cercano un pequeño servicio en un nodo que no hace nada malo con la base, pero su controlador se vuelve loco. Abre 20 conexiones y todo lo demás esperará. Incluso tu código es correcto.
Por supuesto, escribimos un pequeño parche para Bouncer que agregó esta configuración, es decir, limitar los clientes al grupo.
Sería posible hacer esto en el lado de Postgres, es decir, limitar los roles en la base de datos al número de conexiones.
Pero luego pierde la capacidad de comprender por qué no tiene conexión con el servidor. PgBouncer no arroja un error de conexión, siempre devuelve la misma información. Y no puedes entender: tal vez tu contraseña ha cambiado, tal vez la base de datos simplemente dejó de funcionar, tal vez algo anda mal. Pero no hay ningún diagnóstico. Si no se puede establecer la sesión, no sabrá por qué no se puede realizar.
En cierto momento, miras los gráficos de la aplicación y ves que la aplicación no funciona.
Mire la parte superior y vea que Bouncer tiene un solo subproceso. Este es un punto de inflexión en la vida del servicio. Entiendes que te estabas preparando para escalar la base de datos en un año y medio y que necesitas escalar el pooler.
Hemos llegado a la conclusión de que necesitamos más PgBouncers.
Bouncer ha sido ligeramente parcheado.
Y lo hicieron para que se puedan levantar varios Bouncers con la reutilización del puerto TCP. Y el sistema operativo ya transfiere automáticamente las conexiones TCP entrantes entre ellos por turnos.
Esto es transparente para los clientes, es decir, parece que tiene un Bouncer, pero tiene fragmentación de conexiones inactivas entre Bouncers en ejecución.
Y en algún momento, podrás notar que estos 3 Bouncers se comen cada uno su núcleo al 100%. Necesitas bastantes Bouncers. ¿Por qué?
Porque tienes TLS. Tienes una conexión cifrada. Y si compara Postgres con y sin TLS, encontrará que la cantidad de conexiones establecidas se reduce en casi dos órdenes de magnitud con el cifrado habilitado, porque el protocolo de enlace TLS consume recursos de la CPU.
Y en la parte superior puedes ver bastantes funciones criptográficas que se ejecutan durante una ola de conexiones entrantes. Dado que nuestro principal puede cambiar entre zonas de disponibilidad, una ola de conexiones entrantes es una situación bastante típica. Es decir, por alguna razón, el antiguo primario no estaba disponible y toda la carga se envió a otro centro de datos. Todos vendrán a saludar a TLS al mismo tiempo.
Y es posible que una gran cantidad de apretones de manos TLS no saluden ya al Bouncer, sino que le aprieten la garganta. Es posible que una ola de conexiones entrantes no se amortigue debido al tiempo de espera. Si vuelve a intentar llegar a la base sin un retroceso exponencial, no volverán una y otra vez en una ola coherente.
A continuación se muestra un ejemplo de 16 PgBouncers que cargan 16 núcleos al 100%.
Hemos llegado al PgBouncer en cascada. Esta es la mejor configuración que podemos lograr en nuestra carga Bouncer. Nuestros Bouncers externos sirven para el protocolo de enlace TCP y los Bouncers internos sirven para agrupaciones reales, a fin de no fragmentar en gran medida las conexiones externas.
En esta configuración, es posible un reinicio suave. Puedes reiniciar todos estos 18 Bouncers uno por uno. Pero mantener dicha configuración es bastante difícil. Los administradores de sistemas, DevOps y las personas realmente responsables de este servidor no estarán muy contentos con este esquema.
Parecería que todas nuestras mejoras se pueden promocionar en código abierto, pero Bouncer no lo soporta muy bien. Por ejemplo, la capacidad de ejecutar múltiples PgBouncers en el mismo puerto se comprometió hace un mes. Hace unos años se realizó una solicitud de extracción con esta función.
O un ejemplo más. En Postgres, puede cancelar una solicitud en ejecución enviando el secreto a otra conexión sin autenticación adicional. Pero algunos clientes simplemente envían un reinicio de TCP, es decir, interrumpen la conexión de red. ¿Qué hará Bouncer con esto? Él no hará nada. Continuará ejecutando la solicitud. Si ha recibido una gran cantidad de conexiones que han sentado la base con pequeñas solicitudes, entonces simplemente desconectar la conexión de Bouncer no será suficiente, aún debe completar aquellas solicitudes que se están ejecutando en la base de datos.
Esto ha sido solucionado y el problema aún no se ha fusionado con el flujo ascendente de Bouncer.
Y así llegamos a la conclusión de que necesitamos nuestro propio pool de conexiones, que será desarrollado, parcheado, en el que será posible solucionar problemas rápidamente y que, por supuesto, debe ser multiproceso.
Establecimos el subproceso múltiple como la tarea principal. Necesitamos poder manejar bien la ola de conexiones TLS entrantes.
Para hacer esto, tuvimos que desarrollar una biblioteca separada llamada Machinarium, que está diseñada para describir los estados de la máquina de una conexión de red como un código de serie. Si observa el código fuente de libpq, verá llamadas bastante complejas que pueden devolverle un resultado y decir: "Llámame un poco más tarde. Ahora mismo tengo IO por ahora, pero cuando pasa el IO, tengo una carga en el procesador. Y este es un esquema de varios niveles. La interacción de la red generalmente se describe mediante una máquina de estados. Muchas reglas como "Si anteriormente recibí un encabezado de paquete de tamaño N, ahora estoy esperando N bytes", "Si envié un paquete SYNC, ahora estoy esperando un paquete con metadatos de resultados". Resulta un código bastante complicado y contrario a la intuición, como si el laberinto se hubiera convertido en un escaneo lineal. Lo hicimos de modo que, en lugar de una máquina de estados, el programador describiera la ruta de interacción principal en forma de código imperativo ordinario. Solo en este código imperativo, debe insertar lugares donde la secuencia de ejecución debe interrumpirse esperando datos de la red, pasando el contexto de ejecución a otra rutina (hilo verde). Este enfoque es similar al hecho de que escribimos el camino más esperado en el laberinto en una fila y luego le agregamos ramas.
Como resultado, tenemos un subproceso que hace que TCP acepte y el round-robin pasa una conexión TPC a muchos trabajadores.
En este caso, cada conexión de cliente siempre se ejecuta en un procesador. Y esto le permite hacerlo compatible con el caché.
Y además, hemos mejorado ligeramente la recopilación de paquetes pequeños en un paquete grande para descargar la pila TCP del sistema.
Además, hemos mejorado el pool transaccional en el sentido de que Odyssey, cuando está configurado, puede enviar CANCELAR y ROLLBACK en caso de una falla en la conexión de red, es decir, si nadie está esperando la solicitud, Odyssey le indicará a la base de datos que no intente cumplir. la solicitud que puede desperdiciar recursos preciosos.
Y siempre que sea posible, mantenemos conexiones con el mismo cliente. Esto evita tener que reinstalar application_name_add_host. Si es posible, entonces no tenemos un reinicio adicional de los parámetros necesarios para el diagnóstico.
Trabajamos en interés de Yandex.Cloud. Y si está utilizando PostgreSQL administrado y tiene instalado un agrupador de conexiones, puede crear una replicación lógica hacia afuera, es decir, dejarnos si lo desea, usando la replicación lógica. El rebotador fuera del flujo de replicación lógica no cederá.
Este es un ejemplo de configuración de replicación lógica.
Además, contamos con soporte para replicación física hacia afuera. En la nube, por supuesto, es imposible, porque entonces el clúster le dará demasiada información sobre sí mismo. Pero en tus instalaciones, si necesitas replicación física a través del pooler de conexiones en Odyssey, es posible.
Odyssey tiene monitoreo totalmente compatible con PgBouncer. Tenemos la misma consola que ejecuta casi todos los mismos comandos. Si falta algo, envía una solicitud de extracción, o al menos un problema en GitHub, completaremos los comandos necesarios. Pero ya tenemos la funcionalidad principal de la consola PgBouncer.
Y por supuesto tenemos reenvío de errores. Devolveremos el error reportado por la base. Obtendrás información de por qué no estás en la base, no solo de que no estás en ella.
Esta función está deshabilitada en caso de que necesite 100% de compatibilidad con PgBouncer. Podemos comportarnos como Bouncer, por si acaso.
Desarrollo
Algunas palabras sobre el código fuente de Odyssey.
Por ejemplo, existen comandos "Pausar/Reanudar". Suelen utilizarse para actualizar la base de datos. Si necesita actualizar Postgres, puede pausarlo en el grupo de conexiones, realizar pg_upgrade y luego reanudarlo. Y desde el lado del cliente, parecerá que la base de datos simplemente se está desacelerando. Esta funcionalidad nos la trajeron personas de la comunidad. Ella aún no ha muerto, pero pronto todo lo será. (Ya está muerto)
Además, una de las nuevas características de PgBouncer es la compatibilidad con la autenticación SCRAM, que también nos trajo una persona que no trabaja en Yandex.Cloud. Ambas son funcionalidades complejas e importantes.
Por lo tanto, me gustaría contarte de qué está hecho Odyssey, en caso de que también quieras escribir algo de código ahora.
Tienes la base Odyssey original, que se basa en dos bibliotecas principales. La biblioteca Kiwi es una implementación del protocolo de mensajes de Postgres. Es decir, el proto 3 nativo de Postgres son mensajes estándar que los frontends y backends pueden intercambiar. Están implementados en la biblioteca Kiwi.
La biblioteca Machinarium es una biblioteca de implementación de subprocesos. Un pequeño fragmento de este Machinarium está escrito en ensamblador. Pero no te preocupes, sólo hay 15 líneas.
Arquitectura Odisea. Hay una máquina principal que ejecuta rutinas. Esta máquina implementa la aceptación de conexiones TCP entrantes y la distribución entre los trabajadores.
Dentro de un trabajador, puede trabajar un controlador para varios clientes. Y también en el hilo principal están girando la consola y el procesamiento de tareas de crone para eliminar conexiones que ya no son necesarias en el grupo.
Odyssey se prueba utilizando el conjunto de pruebas estándar de Postgres. Simplemente ejecutamos install-check a través de Bouncer y a través de Odyssey, obtenemos un div nulo. Hay varias pruebas relacionadas con el formato de fechas que fallan exactamente igual en Bouncer y Odyssey.
Además, hay muchos conductores que tienen sus propias pruebas. Y usamos sus pruebas para probar Odyssey.
Además, debido a nuestra configuración en cascada, tenemos que probar varios paquetes: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey para estar seguros de que si Odyssey está en alguna de las partes de la cascada, también funcione como se esperaba. .
Rastrillo
Usamos Odyssey en producción. Y no sería justo si dijera que todo simplemente funciona. No, es decir, sí, pero no siempre. Por ejemplo, en producción todo funcionó, luego vinieron nuestros amigos de PostgreSQL Professional y dijeron que teníamos una pérdida de memoria. Realmente lo eran, los arreglamos. Pero fue sencillo.
Luego descubrimos que el grupo de conexiones tiene conexiones TLS entrantes y conexiones TLS salientes. Y las conexiones necesitan certificados de cliente y certificados de servidor.
Los certificados de servidor Bouncer y Odyssey se vuelven a leer mediante pcache, pero no es necesario volver a leer los certificados de cliente desde pcache, porque nuestro Odyssey escalable eventualmente depende del rendimiento del sistema al leer este certificado. Esto nos sorprendió porque no descansó inmediatamente. Al principio escalaba linealmente y después de 20 conexiones entrantes simultáneas, este problema se manifestó.
El método de autenticación conectable es la capacidad de autenticarse con herramientas integradas de Linux. En PgBouncer, está implementado de tal manera que hay un subproceso separado esperando una respuesta de PAM y hay un subproceso PgBouncer principal que sirve a la conexión actual y puede pedirles que vivan en el subproceso PAM.
No implementamos esto por una sencilla razón. Tenemos muchas corrientes. ¿Por qué lo necesitamos?
Como resultado, esto puede crear problemas en el sentido de que si tiene autenticación PAM y autenticación no PAM, una gran ola de autenticación PAM puede retrasar significativamente la autenticación no PAM. Es una de esas cosas que no hemos solucionado. Pero si quieres solucionarlo, puedes hacer esto.
Otro problema fue el hecho de que tenemos un hilo que acepta todas las conexiones entrantes. Y luego se transfieren al grupo de trabajadores, donde se llevará a cabo el protocolo de enlace TLS.
Como resultado, si tienes una ola coherente de 20 conexiones de red, todas serán aceptadas. Y en el lado del cliente, libpq comenzará a informar tiempos de espera. De forma predeterminada, son como 000 segundos allí.
Si no pueden ingresar todos a la base al mismo tiempo, entonces no pueden ingresar a la base, porque todo esto puede cubrirse mediante un reintento no exponencial.
Terminamos copiando el esquema PgBouncer aquí para limitar la cantidad de conexiones TCP que aceptamos.
Si vemos que estamos aceptando conexiones, pero al final no tienen tiempo de darse la mano, las ponemos en cola para que no consuman recursos de CPU. Esto lleva a que no se pueda realizar un protocolo de enlace simultáneo para todas las conexiones llegadas. Pero al menos alguien entrará en la base de datos, incluso si la carga es lo suficientemente fuerte.
Roadmap
¿Qué te gustaría ver en el futuro en Odyssey? ¿Qué estamos dispuestos a desarrollar nosotros mismos y qué esperamos de la comunidad?
Para agosto de 2019.
Así era la hoja de ruta de Odyssey en agosto:
- Queríamos autenticación SCRAM y PAM.
- Queríamos reenviar las solicitudes de lectura al modo de espera.
- Me gustaría reiniciar en línea.
- Y la posibilidad de pausar en el servidor.
La mitad de esta hoja de ruta la hemos hecho nosotros, y no nosotros. Y esto es bueno. Así que analicemos lo que queda y agreguemos más.
En principio, en Postgres, a partir de 10, es posible especificar session_attrs al conectarse. Puede enumerar todos los hosts de bases de datos en la conexión y decir por qué va a la base de datos: escritura o solo lectura. Y el propio conductor elegirá el primer host de la lista que más le guste, que cumpla con los requisitos de session_attrs.
Pero el problema con este enfoque es que no controla el retraso de replicación. Es posible que tengas algún tipo de réplica que esté retrasada por un tiempo inaceptable para tu servicio. Para poder ejecutar solicitudes de lectura con todas las funciones en una réplica, de hecho, necesitamos admitir en Odyssey la capacidad de no funcionar cuando es imposible leer.
Odyssey tiene que ir a la base de datos de vez en cuando y preguntar por la distancia de replicación desde la primaria. Y si ha alcanzado el límite, no permita que entren nuevas solicitudes a la base de datos, dígale al cliente que necesita reiniciar las conexiones y, posiblemente, seleccione otro host para ejecutar las solicitudes. Esto permitirá que la base de datos restaure rápidamente el retraso de replicación y regrese nuevamente para responder con una consulta.
Es difícil nombrar las fechas de implementación porque es de código abierto. Pero espero que no dos años y medio como los colegas de PgBouncer. Esta es la característica que me gustaría ver en Odyssey.
Pero hay una declaración preparada a nivel de protocolo de mensajes en proto3. Y este es el lugar donde la información que se está creando en la declaración preparada llega de forma estructurada. Y podríamos apoyar el entendimiento de que en alguna conexión de servidor el cliente solicitó crear declaraciones preparadas. E incluso si la transacción se cierra, aún necesitamos mantener conectados al servidor y al cliente.
Pero aquí surge una discrepancia en el diálogo, porque alguien dice que es necesario comprender qué declaraciones preparadas creó el cliente y compartir la conexión del servidor entre todos los clientes que crearon esta conexión al servidor, es decir, quién creó dicha declaración preparada.
Andrés Freund dijo que si llega a usted un cliente que ya había creado una declaración preparada en otra conexión de servidor, entonces créela para él. Pero parece un poco incorrecto ejecutar consultas en la base de datos en lugar del cliente, pero desde el punto de vista del desarrollador que escribe el protocolo para interactuar con la base de datos, sería conveniente si simplemente se le proporcionara una conexión de red. que tiene una solicitud tan preparada.
Y una característica más que debemos implementar. Ahora contamos con monitorización compatible con PgBouncer. Podemos devolver el tiempo promedio de ejecución de la consulta. Pero el tiempo promedio es la temperatura promedio en el hospital: alguien tiene frío, alguien tiene calor; en promedio, todos están sanos. No es cierto.
Necesitamos implementar soporte para percentiles, lo que indicaría que hay solicitudes lentas que consumen recursos y haría que el monitoreo sea más aceptable.
Lo más importante es que quiero la versión 1.0 (la versión 1.1 ya ha sido lanzada). El hecho es que ahora Odyssey está en la versión 1.0rc, es decir, versión candidata. Y todo el rastrillo que enumeré se solucionó exactamente con la misma versión, excepto la pérdida de memoria.
¿Qué significará la versión 1.0 para nosotros? Estamos implementando el Odyssey en nuestras bases. Ya se está ejecutando en nuestras bases de datos, pero cuando alcanza el punto de 1 de solicitudes por segundo, entonces podemos decir que esta es una versión de lanzamiento y esta es una versión que se puede llamar 000.
Varias personas en la comunidad han pedido más pausa y SCRAM en la versión 1.0. Pero esto significará que tendremos que implementar la próxima versión en producción, porque ni SCRAM ni la pausa se han fusionado todavía. Pero lo más probable es que este problema se resuelva con bastante rapidez.
Estoy esperando tu solicitud de extracción. Y también me gustaría saber qué problemas tienes con Bouncer. Discutamos sobre ellos. Quizás podamos implementar algunas funciones que necesite.
Con esto concluye mi parte, me gustaría saber de usted. ¡Gracias!
preguntas
Si pongo mi propio nombre_aplicación, ¿se lanzará correctamente, incluso en la agrupación de transacciones en Odyssey?
¿Odisea o gorila?
En Odisea. El saltador es arrojado.
Haremos un set.
Y si mi conexión real salta sobre otras conexiones, ¿se transmitirá?
Haremos un conjunto de todos los parámetros que se enumeran. No puedo saber si nombre_aplicación está en esta lista. Parece que lo vio allí. Estableceremos todos los mismos parámetros. Con una solicitud, el conjunto hará todo lo que instaló el cliente durante el inicio.
¡Gracias Andrey por el informe! ¡Buen informe! Me alegro de que Odyssey se desarrolle cada vez más rápido cada minuto. Me gustaría seguir igual. Ya le hemos pedido que tenga una conexión de múltiples fuentes de datos para que Odyssey pueda conectarse a diferentes bases de datos al mismo tiempo, es decir, al maestro esclavo, y luego conectarse automáticamente al nuevo maestro después de una conmutación por error.
Sí, creo recordar esa discusión. Ahora hay varios almacenes. Pero no hay cambio entre ellos. Por nuestra parte, debemos consultar al servidor que aún está vivo y entender que se ha producido una conmutación por error, quien llamará a pg_recovery. Tengo una forma estándar de entender que no llegamos al maestro. ¿Y debemos entender de alguna manera los errores o cómo? Es decir, la idea es interesante, se está discutiendo. Escribe más comentarios. Si tienes manos trabajando que conocen C, esto es generalmente maravilloso.
La cuestión del escalado entre réplicas también nos interesa, porque queremos que la adopción de clústeres replicados sea lo más sencilla posible para los desarrolladores de aplicaciones. Pero aquí me gustaría más comentarios, es decir, cómo hacerlo, cómo hacerlo bien.
La pregunta también se refiere a las réplicas. Resulta que tienes un maestro y varias réplicas. Y está claro que acuden con menos frecuencia a la réplica que al maestro para conectarse, porque pueden tener una diferencia. Usted dijo que la diferencia en los datos puede ser tal que su negocio no le satisfará y no irá allí hasta que se replique. Al mismo tiempo, si no fue allí durante mucho tiempo y luego comenzó a ir, los datos que necesita no estarán disponibles de inmediato. Es decir, si vamos constantemente al maestro, entonces el caché se calienta allí y el caché queda un poco atrás en la réplica.
Sí, es verdad. No habrá bloques de datos en pcache que desee, en caché real no habrá información sobre las tablas que desee, no habrá consultas analizadas en los planes, nada en absoluto.
Y cuando tienes algún tipo de clúster y agregas una nueva réplica allí, mientras se inicia, todo está mal en él, es decir, su caché aumenta.
Se me ocurrió la idea. El enfoque correcto sería ejecutar primero un pequeño porcentaje de consultas en la réplica, lo que calentaría el caché. A grandes rasgos, tenemos la condición de que no debemos estar a más de 10 segundos del maestro. Y esta condición no debería incluirse en una sola ola, sino sin problemas para algunos clientes.
Sí, aumenta de peso.
Esta es una buena idea. Pero primero debes implementar este cierre. Primero debemos apagarlo y luego pensaremos en cómo encenderlo. Esta es una gran característica para activar sin problemas.
nginx tiene esta opción slowly start
en el clúster del servidor. Y poco a poco va aumentando la carga.
Sí, gran idea, la intentaremos cuando lleguemos a eso.
Fuente: habr.com