La traducción del artículo fue preparada especialmente para estudiantes del curso "Base de datos" . ¿Es interesante desarrollar en esta dirección? Te invitamos a la jornada de puertas abiertas , donde hablamos en detalle sobre el programa, las características del formato en línea, las competencias y las perspectivas profesionales que esperan a los graduados después de la capacitación.

PostgreSQL y configuración de consistencia de registro para cada conexión particular
En Compose, tenemos que lidiar con muchas bases de datos, que es lo que nos da la oportunidad de conocer más acerca de su funcionalidad y desventajas. A medida que aprendemos a amar las características funcionales de las nuevas bases de datos, a veces comenzamos a pensar en lo bueno que sería si funciones similares estuvieran presentes en herramientas más maduras con las que hemos estado trabajando durante mucho tiempo. Una de las nuevas características que PostgreSQL quería ver era su consistencia de escritura personalizada en todo el clúster. Y resultó que ya lo tenemos, y hoy queremos compartir con usted información sobre cómo puede usarlo.
¿Por qué necesito esto?
El comportamiento de un clúster depende de su aplicación. Tomemos, por ejemplo, una solicitud para pagar facturas. Necesitará una coherencia del 100% en el clúster, por lo que deberá habilitar las confirmaciones síncronas para que su base de datos espere a que se realicen todos los cambios. Sin embargo, si su aplicación es una red social de rápido crecimiento, entonces probablemente preferirá una coherencia del 100% con una respuesta rápida. Para lograr esto, puede usar confirmaciones asincrónicas en su clúster.
Conoce el compromiso
Debe comprometer la consistencia de los datos y el rendimiento. PostgreSQL pasa de la coherencia, porque la configuración predeterminada en este caso es predecible y sin sorpresas inesperadas. Y ahora nos familiarizaremos con los compromisos.
Compromiso 1: rendimiento
Si el clúster PostgreSQL no requiere coherencia, puede funcionar de forma asíncrona. La grabación se realiza al líder del clúster y se enviarán actualizaciones a sus réplicas después de unos pocos milisegundos. Cuando se requiere coherencia para un clúster PostgreSQL, debería funcionar de forma sincrónica. El registro se realizará en el líder del clúster, que enviará actualizaciones a las réplicas y esperará la confirmación de que todos hicieron un registro antes de enviar la confirmación al cliente que inició el registro de que fue exitoso. La diferencia práctica entre estos enfoques es que el método asincrónico requiere dos saltos de red, mientras que el método síncrono requiere cuatro.
Compromiso 2: Consistencia
El resultado en caso de mal funcionamiento de un líder en estos dos enfoques también será diferente. Si el trabajo se realiza de forma asíncrona, cuando se produce dicho error, no todos los registros serán confirmados por las réplicas. ¿Cuánto se perderá? Depende de la aplicación en sí y de la eficiencia de la replicación. La replicación compuesta evitará que la réplica se convierta en un líder si la cantidad de información que contiene es de 1 MB menos que en el líder, es decir, se pueden perder hasta 1 MB de registros durante la operación asincrónica.
En modo síncrono, esto no sucede. Si el líder falla, todas las réplicas se actualizan, ya que cualquier registro confirmado en el líder debe confirmarse en las réplicas. Aquí está: coherencia.
Tiene sentido utilizar un comportamiento sincrónico en una aplicación para pagar facturas, donde la coherencia tiene una clara ventaja al encontrar un compromiso entre la coherencia y el rendimiento. Lo más importante para dicha aplicación son los datos válidos. Ahora recuerde acerca de la red social, en la cual la tarea principal es mantener la atención del usuario, respondiendo a las solicitudes lo más rápido posible. En este caso, el rendimiento con menos saltos de red y menos confirmaciones de espera será una prioridad. Sin embargo, la compensación entre rendimiento y consistencia no es la única en la que pensar.
Compromiso 3: fallas
Es muy importante comprender cómo se comporta el clúster durante una falla. Considere una situación en la que una o más réplicas fallan. Cuando las confirmaciones se procesan de forma asíncrona, el líder continuará funcionando, es decir, recibirá y procesará registros sin esperar las réplicas faltantes. Cuando las réplicas regresan al clúster, se ponen al día con el líder. Con la replicación sincrónica, si las réplicas no responden, el líder no tendrá otra opción y continuará esperando la confirmación de la confirmación hasta que la réplica regrese al clúster y pueda aceptar y confirmar el registro.
¿Una conexión por transacción?
Cada aplicación necesita un tipo especial de combinación de consistencia y rendimiento. A menos, por supuesto, que sea nuestra aplicación de facturación, que creemos que es completamente consistente, o nuestra aplicación de red social casi efímera. En todos los demás casos, habrá momentos en que algunas operaciones deben ser sincrónicas y otras asincrónicas. Es posible que no desee que el sistema espere a que se cierre el mensaje enviado al chat, pero si el pago se realiza en la misma aplicación, tendrá que esperar.
Todas estas decisiones, por supuesto, son tomadas por el desarrollador de la aplicación. Las decisiones correctas sobre cuándo aplicar este o aquel enfoque ayudarán a aprovechar al máximo el clúster. Es importante que el desarrollador pueda cambiar entre ellos en el nivel SQL para conexiones y transacciones.
Proporcionando control en la práctica
Por defecto, PostgreSQL proporciona consistencia. Esto es controlado por el parámetro del servidor synchronous_commit
. Por defecto está remote_write
, pero tiene otras tres opciones: local
, remote_write
u off
.
Cuando el parámetro se off
, todas las confirmaciones síncronas se detienen, incluso en el sistema local. El parámetro en local determina el modo síncrono para el sistema local, pero las escrituras en las réplicas son asíncronas. Remote_write
va más allá: las escrituras en las réplicas se realizan de forma asincrónica, pero se devuelven cuando la réplica recibió el registro pero no lo escribió en el disco.
Teniendo en cuenta la gama de opciones disponibles, elegimos el comportamiento y, recordando que hay registros sincrónicos, elegiremos local
para confirmaciones asíncronas a través de la red, mientras que las confirmaciones locales son sincrónicas.
Ahora, le diremos cómo configurar esto en un instante, pero imagine que configuramos synchronous_commit
en local
para el servidor. Nos preguntamos si el parámetro synchronous_commit
se puede cambiar sobre la marcha, y resultó que no solo es posible, incluso hay dos formas de hacerlo. El primero es configurar su sesión de conexión de la siguiente manera:
SET SESSION synchronous_commit TO ON; // Your writes go here
Todos los registros posteriores en la sesión confirmarán las operaciones de escritura para las réplicas antes de devolver un resultado positivo al cliente conectado. A menos que, por supuesto, cambie de nuevo la configuración synchronous_commit
. Puede omitir la parte SESSION
del comando porque estará en el valor predeterminado.
La segunda forma es buena cuando solo quiere asegurarse de obtener una replicación síncrona para una sola transacción. En muchas bases de datos NoSQL, el concepto de transacciones no existe, pero existe en PostgreSQL. En este caso, usted inicia la transacción y luego establece synchronous_commit
en on
antes de escribir en la transacción. COMMIT
la transacción utilizando cualquier valor del parámetro synchronous_commit
que se estableció en ese momento, aunque es mejor establecer la variable de antemano para asegurarse de que otros desarrolladores entiendan que los registros no son asíncronos.
BEGIN; SET LOCAL synchronous_commit TO ON; // Your writes go here COMMIT;
Todas las confirmaciones de transacciones ahora se confirmarán como escritas en las réplicas antes de que la base de datos devuelva una respuesta positiva al cliente conectado.
Configuración de PostgreSQL
Antes de eso, imaginamos un sistema PostgreSQL con synchronous_commit
establecido en local
. Para que esto sea real en el lado del servidor, deberá establecer dos parámetros de configuración del servidor. Otro parámetro synchronous_standby_names
se hará cargo cuando synchronous_commit
está synchronous_commit
. Determina qué réplicas son elegibles para confirmaciones síncronas, y lo configuraremos en *
, lo que significará que todas las réplicas están habilitadas. Estos valores generalmente se configuran en el archivo de configuración agregando:
synchronous_commit = local synchronous_standby_names='*'
Al establecer el parámetro synchronous_commit
en local
, creamos un sistema en el que las unidades locales permanecen sincrónicas, pero las confirmaciones de réplica de red son asíncronas de manera predeterminada. A menos, por supuesto, que decidamos hacer estas confirmaciones sincrónicas, como se muestra arriba.
Si siguió el desarrollo del proyecto Governor , es posible que haya notado algunos cambios recientes ( 1 , 2 ), que permitieron a los usuarios de Governor probar estos parámetros y controlar su coherencia.
Unas pocas palabras más ...
Hace apenas una semana, les diría que no es posible ajustar PostgreSQL tan finamente. Fue entonces cuando Kurt, un miembro del equipo de la plataforma Compose, insistió en que existía esa oportunidad. Pacificó mis objeciones y encontró lo siguiente en la documentación de PostgreSQL:

Este parámetro se puede cambiar en cualquier momento. El comportamiento de cualquier transacción está determinado por la configuración vigente al confirmar. Por lo tanto, es posible y útil que las confirmaciones se confirmen sincrónicamente para algunas transacciones y asincrónicamente para otras. Por ejemplo, para forzar que una sola transacción de multistatement
declaraciones se confirme de forma asíncrona cuando el valor predeterminado del parámetro es el opuesto, establezca SET LOCAL synchronous_commit TO OFF
en la transacción.
Con esta pequeña modificación en el archivo de configuración, les dimos a los usuarios la capacidad de controlar su consistencia y rendimiento.