Configuración de Replicación Síncrona para Alta Disponibilidad en PostgreSQL
Configurar PostgreSQL para alta disponibilidad (HA) es crucial para cualquier aplicación de misión crítica. Si bien la replicación asíncrona ofrece beneficios de rendimiento, inherentemente conlleva el riesgo de pérdida de datos si el servidor principal falla antes de que los cambios se transmitan por completo al servidor en espera. La replicación de streaming síncrona resuelve esto garantizando que una transacción solo se considere confirmada una vez que los datos se hayan escrito correctamente en el WAL (Write-Ahead Log) tanto del servidor principal como de al menos un servidor en espera designado. Esto asegura un Objetivo de Punto de Recuperación (RPO) de cero.
Esta guía completa le muestra los pasos de configuración esenciales necesarios para establecer una configuración de replicación de PostgreSQL robusta y sin pérdida de datos. Nos centraremos en parámetros críticos como wal_level y synchronous_commit que sustentan esta arquitectura de alta disponibilidad.
Prerrequisitos
Antes de comenzar, asegúrese de tener dos servidores PostgreSQL configurados (Principal y en Espera) ejecutando versiones principales idénticas de PostgreSQL. Ambos servidores deben tener conectividad de red. Para esta guía, asumimos:
- Nombre de host/IP Principal:
pg_primary - Nombre de host/IP en Espera:
pg_standby - Usuario de Replicación:
repl_user(creado con permisos apropiados) - Nombre de Base de Datos:
mydb
Paso 1: Configuración del Servidor Principal
El servidor principal requiere configuraciones específicas para habilitar la replicación de streaming y administrar el Write-Ahead Log (WAL) necesario para los commits síncronos.
A. Ajuste de postgresql.conf en el Principal
Edite el archivo postgresql.conf del servidor principal. Los siguientes parámetros son obligatorios para la replicación de streaming:
# --- Requerido para Replicación ---
listen_addresses = '*' # Permite conexiones desde el servidor en espera
wal_level = replica # Debe ser 'replica' o superior (ej. 'logical')
max_wal_senders = 10 # Conexiones concurrentes máximas desde los servidores en espera
max_replication_slots = 10 # Ranuras necesarias para flujos de replicación persistentes
# --- Esencial para Commit Síncrono ---
synchronous_standby_names = '1 (standby_app_name)' # Especifica los servidores en espera requeridos
# --- Opcional pero Recomendado ---
wal_log_hints = on # Recomendado para una replicación más segura, aunque aumenta el volumen de WAL
shared_preload_libraries = 'pg_stat_statements' # Si se utiliza monitorización
Explicación de Parámetros Clave:
wal_level = replica: Esto asegura que se escriba información suficiente en el WAL para permitir que un servidor en espera reconstruya el estado de la base de datos. Para commits síncronos, este nivel es el requisito mínimo.synchronous_standby_names: Esta es la configuración central para definir qué servidores en espera deben confirmar las escrituras. Lo definimos usando la sintaxis(N (nombre_servidor_en_espera)). SiN=1, al menos un servidor en espera debe confirmar la escritura antes de que la transacción se confirme.
B. Configuración de Autenticación Basada en Host (pg_hba.conf)
El servidor principal debe permitir que el usuario de replicación de los servidores en espera se conecte con fines de replicación.
Agregue una entrada a pg_hba.conf en el servidor principal:
# TYPE DATABASE USER ADDRESS METHOD
host replication repl_user pg_standby/32 scram-sha-256
Reemplace pg_standby/32 con la dirección IP o subred real de su servidor en espera.
C. Creación de la Ranura y el Usuario de Replicación
Conéctese a PostgreSQL en el servidor principal para crear el usuario y la ranura de replicación necesarios.
1. Crear Usuario de Replicación:
CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'una_contraseña_segura';
2. Crear Ranura de Replicación:
Esta ranura asegura que los segmentos WAL se conserven hasta que el servidor en espera confirme la recepción, evitando la pérdida de datos si el servidor en espera se desconecta temporalmente.
SELECT pg_create_physical_replication_slot('standby_app_name');
- Nota sobre Nomenclatura: El nombre proporcionado aquí (
standby_app_name) debe coincidir con el nombre especificado ensynchronous_standby_namesen el servidor principal.
D. Reinicio del Servidor Principal
Aplique todos los cambios de configuración reiniciando el servicio PostgreSQL en el servidor principal.
sudo systemctl restart postgresql
Paso 2: Configuración del Servidor en Espera
El servidor en espera se configura para transmitir registros WAL desde el principal utilizando una configuración de recuperación.
A. Copia de Seguridad Base
Antes de iniciar la transmisión, el servidor en espera necesita una copia completa del directorio de datos del principal. Detenga PostgreSQL en el servidor en espera primero.
sudo systemctl stop postgresql
Realice la copia de seguridad base usando pg_basebackup. Reemplace las rutas y los detalles de conexión según sea necesario:
# Ejemplo usando la utilidad pg_basebackup
pg_basebackup -h pg_primary -D /var/lib/postgresql/15/main/ -U repl_user -P -Xs -R -W
-D: El directorio de datos de destino en el servidor en espera.-U: El usuario de replicación.-P: Mostrar progreso.-Xs: Incluir archivos WAL necesarios durante la copia de seguridad base.-R: Crear automáticamente el archivostandby.signaly generar la configuración de conexión necesaria enpostgresql.auto.conf(o configuración de recuperación).
B. Configuración de postgresql.conf en el Servidor en Espera
En el servidor en espera, asegúrese de que postgresql.conf le permita actuar como réplica. La configuración clave aquí es establecer el nombre de la aplicación, que debe coincidir con el nombre de la ranura utilizada en el servidor principal.
# --- Requerido en Servidor en Espera ---
primary_conninfo = 'host=pg_primary port=5432 user=repl_user password=una_contraseña_segura application_name=standby_app_name'
hot_standby = on # Permite consultas de lectura durante el modo de recuperación/en espera
C. Inicio del Servidor en Espera
Inicie el servicio PostgreSQL en el servidor en espera.
sudo systemctl start postgresql
Paso 3: Verificación y Prueba de Commit Síncrono
Una vez que ambos servidores estén en ejecución, verifique la conexión y luego pruebe el comportamiento síncrono.
A. Verificación del Estado de Replicación
Conéctese a la base de datos principal y verifique la vista pg_stat_replication:
SELECT client_addr, application_name, state, sync_state FROM pg_stat_replication;
Debería ver una entrada para standby_app_name con sync_state como sync.
B. Prueba de Commit Síncrono
El parámetro global que dicta cuánto espera PostgreSQL es synchronous_commit. Para RPO=0, debe usar un valor que fuerce la sincronización.
1. Configuración del Comportamiento Global
Si configuró synchronous_standby_names en el servidor principal como se muestra en el Paso 1, el comportamiento predeterminado forzará la espera de los servidores en espera requeridos si synchronous_commit se establece en on (el valor predeterminado) o remote_write.
Para la garantía más sólida, configúrelo explícitamente en postgresql.conf a remote_write o remote_apply (si necesita que el servidor en espera haya volcado los datos en el disco, no solo que los haya recibido).
# En postgresql.conf en el Principal
synchronous_commit = remote_write
Advertencia: Establecer
synchronous_commit = remote_writeoonaumenta significativamente la latencia de las transacciones en comparación con los modos asíncronos (offolocal). Esta latencia se correlaciona directamente con la velocidad de la red entre el servidor principal y el servidor en espera síncrono.
2. Prueba Dentro de una Transacción
Para probar transaccionalmente (sin requerir un cambio de configuración global), puede establecerlo por sesión o transacción:
-- Conectarse al Principal
BEGIN;
SET LOCAL synchronous_commit = remote_write;
INSERT INTO sales (item, amount) VALUES ('Widget A', 100);
-- Este INSERT se bloqueará hasta que 'standby_app_name' confirme la recepción.
COMMIT;
-- El COMMIT tiene éxito solo después de que el servidor en espera confirme la escritura WAL.
Si la conexión al servidor en espera síncrono se pierde durante la transacción, el principal esperará indefinidamente (si el servidor en espera se desconecta limpiamente) o recurrirá según la configuración synchronous_commit_fallback_on_error (con el valor predeterminado on, lo que significa que la transacción podría fallar o colgarse si el principal no puede confirmar el estado síncrono).
Mejores Prácticas para HA Síncrona
- Usar Servidores en Espera Dedicados: Asigne solo servidores en espera que estén físicamente cerca (baja latencia) del principal a su lista de replicación síncrona. Una alta latencia afectará gravemente el rendimiento de escritura.
- Monitorizar el Retraso de Replicación: Incluso en modo síncrono, monitorice el retraso del servidor en espera. Un servidor en espera lento que todavía está técnicamente 'sincronizado' pero que tarda demasiado en procesar WAL puede afectar la experiencia del usuario.
- Recurso de Conexión: Comprenda la configuración
synchronous_commit_fallback_on_error. Si se establece enoff, un fallo de comunicación con el servidor en espera síncrono durante un commit provocará que la transacción en el principal falle, evitando una posible divergencia de datos, pero afectando inmediatamente la disponibilidad. - Usar Múltiples Servidores en Espera: Para una redundancia máxima dentro de una configuración síncrona, configure
synchronous_standby_names = '2 (standby1, standby2)'para requerir commits de dos servidores en espera distintos.