Tutoriales 11 min de lectura

Replicación master-slave en PostgreSQL — alta disponibilidad paso a paso

Guía completa para configurar replicación streaming en PostgreSQL con un servidor primario y una réplica de solo lectura para alta disponibilidad y distribución de carga.

Diagrama de replicación PostgreSQL mostrando servidor primario sincronizando datos con réplica de solo lectura
Diagrama de replicación PostgreSQL mostrando servidor primario sincronizando datos con réplica de solo lectura

Una base de datos sin réplica es un punto único de falla. Si el disco muere, si el servidor se cae, si una actualización sale mal — tu ERP, tu CRM, tu e-commerce se detienen. Con replicación, una segunda copia de tu base de datos se mantiene sincronizada en otro servidor, lista para tomar el control en minutos.

En esta guía vas a configurar replicación streaming en PostgreSQL con un servidor primario y una réplica de solo lectura — el esquema de alta disponibilidad más común y práctico para la mayoría de las empresas.

Arquitectura

┌─────────────────┐         ┌─────────────────┐
│    PRIMARIO      │  WAL    │    RÉPLICA       │
│  10.0.1.10       │────────▶│  10.0.1.11       │
│                  │ stream  │                  │
│  Lecturas ✅     │         │  Lecturas ✅     │
│  Escrituras ✅   │         │  Escrituras ❌   │
│                  │         │  (solo lectura)  │
└─────────────────┘         └─────────────────┘
     ▲                           ▲
     │                           │
  App (ERP, CRM)          Reportes, BI
  Escrituras              Consultas pesadas

El primario acepta todas las escrituras y envía los cambios (WAL — Write Ahead Log) a la réplica en tiempo real. La réplica aplica los cambios y está disponible para consultas de solo lectura. Si el primario falla, la réplica puede promoverse a primario.

Requisitos previos

Dos servidores Ubuntu 24.04 con PostgreSQL 16 instalado en ambos:

  • Primario: 10.0.1.10
  • Réplica: 10.0.1.11

Ambos servidores deben poder comunicarse por el puerto 5432. Configura tu firewall UFW:

# En el primario: permitir conexión desde la réplica
sudo ufw allow from 10.0.1.11 to any port 5432 comment 'PostgreSQL replicación'

# En la réplica: permitir conexión desde el primario (para pg_basebackup)
sudo ufw allow from 10.0.1.10 to any port 5432 comment 'PostgreSQL primario'

Paso 1: Configurar el servidor primario

Crear usuario de replicación

En el primario, crea un usuario dedicado para la replicación:

sudo -u postgres psql
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'contraseña_replica_segura';

Configurar pg_hba.conf

Permite la conexión de replicación desde la réplica:

sudo tee -a /etc/postgresql/16/main/pg_hba.conf > /dev/null <<EOF

# Replicación
host    replication    replicator    10.0.1.11/32    scram-sha-256
EOF

Configurar postgresql.conf

Edita la configuración del primario para habilitar la replicación:

sudo nano /etc/postgresql/16/main/postgresql.conf

Modifica o agrega estas líneas:

# Escuchar en todas las interfaces
listen_addresses = '*'

# WAL (Write Ahead Log)
wal_level = replica
max_wal_senders = 5
wal_keep_size = 1GB

# Archivado de WAL (recomendado para point-in-time recovery)
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/16/wal_archive/%f'

Crea el directorio de archivo WAL:

sudo mkdir -p /var/lib/postgresql/16/wal_archive
sudo chown postgres:postgres /var/lib/postgresql/16/wal_archive

Reinicia PostgreSQL:

sudo systemctl restart postgresql

Paso 2: Preparar la réplica

Detener PostgreSQL en la réplica

sudo systemctl stop postgresql

Limpiar el directorio de datos

La réplica necesita empezar con una copia exacta del primario. Borra los datos actuales:

sudo rm -rf /var/lib/postgresql/16/main/*

Cuidado

Este comando borra todos los datos de PostgreSQL en la réplica. Si la réplica tiene datos que necesitas conservar, haz un backup antes. En una instalación nueva, el directorio solo contiene la configuración por defecto.

Copiar los datos del primario con pg_basebackup

sudo -u postgres pg_basebackup \
  -h 10.0.1.10 \
  -U replicator \
  -D /var/lib/postgresql/16/main \
  -Fp -Xs -P -R

Desglose de los parámetros:

ParámetroFunción
-h 10.0.1.10IP del servidor primario
-U replicatorUsuario de replicación
-D ...Directorio destino (datos de la réplica)
-FpFormato plain (archivos tal cual)
-XsIncluir WAL por streaming
-PMostrar progreso
-RCrear automáticamente el archivo standby.signal y configurar la conexión

El proceso tomará desde segundos hasta minutos dependiendo del tamaño de tu base de datos. Verás el progreso en porcentaje.

Paso 3: Verificar la configuración de la réplica

El flag -R de pg_basebackup creó automáticamente dos cosas:

  1. standby.signal — archivo vacío que le dice a PostgreSQL que arranque como réplica
  2. Conexión primaria en postgresql.auto.conf — la cadena de conexión al primario

Verifica:

# Debe existir el archivo standby.signal
ls -la /var/lib/postgresql/16/main/standby.signal

# Debe tener la conexión al primario
cat /var/lib/postgresql/16/main/postgresql.auto.conf

Deberías ver algo como:

primary_conninfo = 'user=replicator password=contraseña_replica_segura host=10.0.1.10 port=5432'

Configurar la réplica como hot standby

Edita postgresql.conf de la réplica para permitir consultas de lectura:

sudo nano /etc/postgresql/16/main/postgresql.conf
hot_standby = on

Paso 4: Arrancar la réplica

sudo systemctl start postgresql

Verifica en los logs que la replicación está funcionando:

sudo tail -20 /var/log/postgresql/postgresql-16-main.log

Deberías ver mensajes como:

LOG:  entering standby mode
LOG:  redo starts at 0/3000028
LOG:  started streaming WAL from primary at 0/4000000 on timeline 1
LOG:  consistent recovery state reached at 0/4000110

Paso 5: Verificar la replicación

Desde el primario

sudo -u postgres psql -c "SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn FROM pg_stat_replication;"

Deberías ver la IP de la réplica con estado streaming:

 client_addr | state     | sent_lsn   | write_lsn  | flush_lsn  | replay_lsn
-------------+-----------+------------+------------+------------+------------
 10.0.1.11   | streaming | 0/4000110  | 0/4000110  | 0/4000110  | 0/4000110

Si todos los LSN coinciden, la réplica está sincronizada — cero retraso.

Desde la réplica

sudo -u postgres psql -c "SELECT pg_is_in_recovery();"

Debe devolver t (true) — confirmando que es una réplica.

Prueba funcional

Crea datos en el primario y verifica que aparecen en la réplica:

# En el primario
sudo -u postgres psql -c "CREATE TABLE test_replica (id serial, msg text, created_at timestamptz DEFAULT now());"
sudo -u postgres psql -c "INSERT INTO test_replica (msg) VALUES ('Hola desde el primario');"

# En la réplica (debería aparecer en menos de 1 segundo)
sudo -u postgres psql -c "SELECT * FROM test_replica;"
# Verificar que la réplica no acepta escrituras
sudo -u postgres psql -h 10.0.1.11 -c "INSERT INTO test_replica (msg) VALUES ('Intento escribir');"
# ERROR: cannot execute INSERT in a read-only transaction

Paso 6: Monitorear el retraso de replicación

El retraso de replicación (replication lag) es la métrica más importante. Si crece, significa que la réplica se está quedando atrás.

Desde el primario

SELECT
  client_addr,
  state,
  pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes,
  pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) AS lag_pretty
FROM pg_stat_replication;

Desde la réplica

SELECT
  now() - pg_last_xact_replay_timestamp() AS lag_time,
  pg_is_in_recovery() AS is_replica;

Para monitoreo continuo, configura Prometheus con postgres_exporter y crea una alerta cuando el lag supere un umbral (por ejemplo, 30 segundos para replicación asíncrona).

Paso 7: Promover la réplica a primario (failover manual)

Si el primario falla y necesitas que la réplica tome el control:

# En la réplica
sudo -u postgres pg_ctlcluster 16 main promote

O con pg_ctl:

sudo -u postgres pg_ctl promote -D /var/lib/postgresql/16/main

Después de la promoción:

  1. La réplica elimina el archivo standby.signal
  2. Acepta escrituras
  3. Se convierte en el nuevo primario

El failover manual tiene riesgo

Promover la réplica manualmente es un proceso de emergencia. Si el primario original sigue vivo, puedes terminar con dos servidores que aceptan escrituras (split-brain). Para failover automático y seguro, usa Patroni — el estándar de la industria para alta disponibilidad de PostgreSQL.

Replicación síncrona (opcional)

Si no puedes perder ni una sola transacción (finanzas, facturación), puedes cambiar a replicación síncrona. En el primario:

# postgresql.conf del primario
synchronous_commit = on
synchronous_standby_names = 'replica1'

En la réplica, configura su application_name en el primary_conninfo:

primary_conninfo = '... application_name=replica1'

Con replicación síncrona, el primario no confirma una escritura al cliente hasta que la réplica la haya recibido. Esto garantiza cero pérdida de datos pero agrega latencia a cada escritura — úsala solo cuando la integridad de datos es más importante que la velocidad.

Siguientes pasos

Con la replicación funcionando, el siguiente nivel es:

  • Patroni — failover automático con consenso distribuido (etcd/ZooKeeper) para que la réplica se promueva sola si el primario falla
  • PgBouncer — connection pooling para manejar cientos de conexiones sin saturar PostgreSQL
  • pgBackRest — backups incrementales con verificación de integridad y point-in-time recovery
  • Múltiples réplicas — una local para HA, otra remota para DR, otra para BI
  • Bases de datos administradas — nuestro servicio DBA as a Service con monitoreo, mantenimiento y soporte 24/7

Alta disponibilidad

¿Necesitas que tu base de datos nunca se detenga?

Implementamos replicación con failover automático, monitoreo de lag y pruebas de failover periódicas para tu PostgreSQL de producción.

Solicitar evaluación

Preguntas frecuentes

Temas relacionados

#postgresql#replicacion#alta-disponibilidad#bases-de-datos#linux#tutorial

¿Te fue útil? Compártelo

Artículos relacionados

Ver todos

Consultoría gratuita

¿Necesitas alta disponibilidad para tu base de datos?

Implementamos replicación, failover automático y monitoreo de PostgreSQL para que tus datos nunca se detengan.

Solicitar evaluación