Replicación de bases de datos — primaria y multi-primaria
Guía práctica de estrategias de replicación de bases de datos: primaria-réplica, multi-primaria, síncrona vs asíncrona, y cómo manejar failover y resolución de conflictos.
Visión General
La replicación mantiene copias de tus datos en varios nodos: una primaria acepta escrituras, las réplicas aplican el stream y sirven lecturas. Es como sobrevives a una primaria muerta a las 3 de la mañana y cómo escalas lecturas más allá de lo que una sola máquina aguanta. El coste es complejidad — lag, conflictos, split-brain y trade-offs de consistencia que tendrás que diseñar.
Esta guía cubre las estrategias que corren en producción: topologías primaria-réplica (aún llamadas master-slave), configuraciones multi-primaria, modos síncronos vs asíncronos, mecánica de failover y resolución de conflictos. Para los snippets operativos, consulta la receta de replicación de bases de datos. Y si buscas el detalle específico de PostgreSQL, existe la guía completa de replicación en PostgreSQL.
Cuándo Usar
- El tráfico de lectura supera un solo nodo y escalar verticalmente dejó de ser rentable
- Necesitas failover automático, no una restauración de backups de 2 horas
- Copias fuera del sitio para recuperación ante desastres
- Analítica pesada que no debería competir con las queries transaccionales
Replicación Primaria-Réplica
Una primaria gestiona escrituras; las réplicas gestionan lecturas. Sigue siendo la topología más común — los términos “master-slave” y “primaria-réplica” se refieren a lo mismo, y verás ambos en documentación y herramientas antiguas.
Replicación Asíncrona
La primaria confirma localmente y luego envía los cambios a las réplicas. Latencia mínima, pero puedes perder los últimos segundos de escrituras si la primaria muere antes de que las réplicas se pongan al día.
-- MySQL 8.0.22+ (versiones antiguas: CHANGE MASTER TO / START SLAVE)
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='primary_host',
SOURCE_USER='replica',
SOURCE_PASSWORD='password';
START REPLICA;
-- PostgreSQL (streaming replication)
-- Primaria: wal_level = replica, max_wal_senders = 3
-- Standby: primary_conninfo = 'host=primary_host port=5432'
Replicación Semi-Síncrona
La primaria espera a que al menos una réplica confirme la recepción antes de hacer commit. Punto medio entre seguridad y velocidad.
-- MySQL
SET GLOBAL rpl_semi_sync_source_enabled = 1;
SET GLOBAL rpl_semi_sync_source_timeout = 10000; -- 10 segundos
Replicación Síncrona
La primaria espera a que todas las réplicas (o un quórum configurado) confirmen. Cero pérdida de datos, a costa de latencia de escritura.
-- PostgreSQL synchronous_commit
SET synchronous_commit = 'remote_apply';
SET synchronous_standby_names = 'replica1, replica2';
Lag de Replicación
El lag es el retraso entre una escritura en la primaria y su aparición en las réplicas. Qué lo causa y qué hacer:
| Causa | Mitigación |
|---|---|
| Latencia de red | Regiones cercanas, wal_compression |
| Alto volumen de escrituras | Sharding de escrituras, más réplicas |
| Transacciones grandes | Dividir en lotes más pequeños |
| Hardware lento en réplica | Igualar specs de la réplica a la primaria |
| Lecturas compitiendo con apply | Réplicas de lectura dedicadas |
Detectar el Lag
-- PostgreSQL (ejecutar en la réplica)
SELECT
now() - pg_last_xact_replay_timestamp() AS lag;
-- MySQL 8.0.22+
SHOW REPLICA STATUS\G
-- observa Seconds_Behind_Source (Seconds_Behind_Master en versiones antiguas)
Replicación Multi-Primaria
Varios nodos aceptan escrituras — tradicionalmente llamado multi-master. Desbloquea escalado de escrituras y distribución geográfica, y es donde la replicación se complica de verdad.
Escenarios de Conflicto
| Escenario | Conflicto |
|---|---|
| Misma clave insertada | Violación de clave primaria |
| Misma fila actualizada | Last-write-wins o merge |
| Fila borrada en A, actualizada en B | Gana update o flag de conflicto |
| IDs auto-incrementales | IDs duplicados entre primarias |
Estrategias de Resolución de Conflictos
- Last-write-wins — decide el timestamp o vector clock; simple, puede perder escrituras silenciosamente
- Merge — la lógica de la aplicación combina ambos cambios
- Resolución manual — marca los conflictos para revisión humana
- Evitación — particiona los datos para que cada fila tenga un solo escritor; lo más simple y usualmente la respuesta correcta
Failover
Cambiar a una réplica cuando la primaria falla. Las dos variantes:
Failover Manual
# PostgreSQL: promover standby
pg_ctl promote -D /var/lib/postgresql/data
# MySQL 8.0.22+: parar réplica, resetear, promover
STOP REPLICA;
RESET REPLICA ALL;
El failover manual es simple hasta que son las 3 de la mañana y no hay nadie — ahí “lo promovemos a mano” se convierte en una hora de caída.
Failover Automático (Patroni)
# patroni.yml
scope: mycluster
restapi:
listen: 0.0.0.0:8008
connect_address: 10.0.0.1:8008
etcd:
hosts: 10.0.0.10:2379,10.0.0.11:2379,10.0.0.12:2379
postgresql:
data_dir: /var/lib/postgresql/data
pg_hba:
- host replication replicator 10.0.0.0/24 md5
Réplicas de Lectura para Escalado
Enruta lecturas a réplicas, escrituras a la primaria. La aplicación es dueña del enrutado — y de lidiar con el lag.
class DatabaseRouter {
private primary: Pool; // pg.Pool para escrituras
private replicas: Pool[];
private currentReplica = 0;
getWritePool(): Pool {
return this.primary;
}
getReadPool(): Pool {
// Round-robin entre réplicas
const pool = this.replicas[this.currentReplica];
this.currentReplica = (this.currentReplica + 1) % this.replicas.length;
return pool;
}
}
// Uso
const db = new DatabaseRouter();
await db.getWritePool().query('INSERT INTO ...');
const result = await db.getReadPool().query('SELECT ...');
Temas Avanzados
Escenario: Alta Disponibilidad con Patroni + HAProxy
Sistema: cluster PostgreSQL de 3 nodos
- 1 primaria (us-east-1a)
- 2 réplicas (us-east-1b, us-east-1c)
- cluster etcd (3 nodos) para consenso
- HAProxy como balanceador
Topología:
Clientes -> HAProxy -> Primaria (escrituras)
-> Réplica1 (lecturas)
-> Réplica2 (lecturas)
etcd <- Patroni (health checks, elección de líder)
Patroni gestiona: failover automático, reinicio, reconfiguración
Config Patroni:
scope: production
restapi:
listen: 0.0.0.0:8008
etcd:
hosts: 10.0.0.10:2379,10.0.0.11:2379,10.0.0.12:2379
postgresql:
data_dir: /var/lib/postgresql/data
parameters:
wal_level: replica
max_wal_senders: 10
hot_standby: on
synchronous_commit: on
synchronous_standby_names: "FIRST 1 (replica1, replica2)"
recovery_conf:
primary_conninfo: "host=10.0.0.1 port=5432 user=replicator"
Config HAProxy:
listen pg_write
bind *:5432
mode tcp
option tcp-check
tcp-check send GET /master HTTP/1.0\r\n\r\n
tcp-check expect status 200
server pg1 10.0.0.1:5432 check port 8008
server pg2 10.0.0.2:5432 check port 8008 backup
server pg3 10.0.0.3:5432 check port 8008 backup
listen pg_read
bind *:5433
mode tcp
balance roundrobin
option tcp-check
tcp-check send GET /replica HTTP/1.0\r\n\r\n
tcp-check expect status 200
server pg2 10.0.0.2:5432 check port 8008
server pg3 10.0.0.3:5432 check port 8008
Failover automático:
1. Patroni detecta primaria caída (health check falla)
2. etcd ejecuta elección de líder entre réplicas
3. La réplica ganadora se promueve a primaria
4. HAProxy redirige el tráfico automáticamente
5. Las demás réplicas se reconectan a la nueva primaria
Tiempo total: 10-30 segundos
Monitoreo:
| Métrica | Alerta |
|---------|--------|
| Lag de replicación | > 5s |
| Salud Patroni | non-200 |
| Cambios de líder etcd | > 1/h |
| Conexiones activas | > 80% del máx |
| Backlog de WAL | > 1GB |
Lecciones:
- Patroni + etcd da failover automático sólido
- HAProxy distingue primaria/réplica vía API REST de Patroni
- synchronous_commit garantiza cero pérdida de datos
- 3 nodos es el mínimo para quórum (nunca uses 2)
- Prueba el failover regularmente en staging
Errores Comunes
- Ignorar el lag de replicación — una lectura justo después de escribir puede caer en una réplica que aún no la aplicó
- Escribir en réplicas — crea split-brain y datos divergentes
- Sin automatización de failover — minutos de trabajo manual se convierten en una hora de caída
- Vigilar solo
Seconds_Behind_Source— marca cero mientras la réplica aún está aplicando una transacción grande - Réplicas subdimensionadas — si no aguantan el throughput de escritura de la primaria, el lag crece para siempre
Solución de Problemas
- El lag no deja de crecer: localiza primero el cuello de botella — red, I/O de disco en la réplica, o una transacción larga. Divide escrituras masivas en lotes y revisa
pg_stat_replicationpara ver dónde se atasca el stream. - La réplica no logra ponerse al día: si se genera WAL más rápido de lo que la réplica lo aplica, el límite es el apply single-threaded. Activa apply paralelo donde se soporte, o reduce los picos de escritura.
- Replication slot llenando el disco: una réplica muerta mantiene su slot reteniendo WAL en la primaria. Elimínalo con
pg_drop_replication_sloto llenará el volumen y tumbará la primaria. - Split-brain tras un failover: dos nodos creen ser primaria. Para uno inmediatamente, resuelve la divergencia con
pg_rewindy reconéctalo como réplica. Nunca corras dos primarias escribibles fuera de un setup multi-primaria real. - La réplica no arranca tras la promoción: revisa
primary_conninfoy las credenciales de replicación — una réplica mal repuntada falla silenciosamente en los logs.
Ver También
Preguntas frecuentes
¿La replicación reemplaza los backups?
No. La replicación protege contra fallos de nodo, no contra corrupción, ransomware o un DROP TABLE accidental — ese tipo de daño se replica a todos los nodos en segundos. Mantén backups separados y probados.
¿Debería usar replicación síncrona o asíncrona?
Asíncrona para la mayoría de cargas — no frena las escrituras. Usa síncrona (o synchronous_commit = remote_apply) para datos donde perder los últimos segundos de transacciones es inaceptable, aceptando el coste de latencia.
¿Cómo manejo cambios de esquema en sistemas replicados?
Usa herramientas de cambio de esquema online (pt-online-schema-change, gh-ost, o DDL online nativo) para que el DDL no bloquee las réplicas. Aplica en la primaria y deja que replique — aplicar cambios de esquema directo en réplicas rompe el stream.
¿Cómo manejo el split-brain?
Prevenir gana a resolver: Patroni usa quórum de etcd para que solo un nodo tenga el lock de líder, y degrada a solo-lectura si etcd no responde. Si ocurre igual, para un nodo inmediatamente, rebobina la divergencia con pg_rewind y reconéctalo como réplica.
¿Puedo replicar entre proveedores cloud?
Sí, pero espera más latencia y costes de egress. La replicación lógica es la opción práctica aquí — puedes sincronizar solo las tablas que necesitas en vez de enviar todo el WAL.
¿Cuánto lag de replicación es aceptable?
La analítica tolera minutos. Las lecturas de cara al usuario necesitan menos de un segundo o una ruta de vuelta a la primaria. Las escrituras financieras necesitan replicación síncrona — tolerancia cero.
¿Cuál es el tamaño mínimo de cluster para failover automático?
Tres nodos, siempre. Los sistemas por quórum (Patroni+etcd) no pueden elegir líder con dos — un nodo caído no deja mayoría. Los setups "HA" de dos nodos son la clásica falsa economía.
Recursos Relacionados
Replicación de bases de datos con PostgreSQL y MySQL
Configura y gestiona replicación de bases de datos para alta disponibilidad, escalado de lecturas y recuperación ante desastres con arquitecturas primaria-réplica.
GuideDesnormalización: espacio por velocidad de lectura
Guía práctica de desnormalización de bases de datos: cuándo cambiar almacenamiento por rendimiento de lectura y mantener datos consistentes.
GuideACID vs BASE — Modelos de Consistencia Explicados
Guía práctica que compara los modelos de consistencia ACID y BASE: cuándo elegir consistencia fuerte, cuándo aceptar la eventual y cómo afecta al diseño.
GuideEstrategias de Indexación — Desde B-Trees hasta BRIN
Guía práctica de índices de bases de datos: B-Trees, Hash, GIN, GiST, BRIN e índices parciales. Aprende cuándo usar cada uno y cómo evitar errores comunes de indexación.
GuideRéplicas de Lectura: Escala Lecturas Sin Tocar tu App
Guía de producción sobre réplicas de lectura: configuración de replicación streaming, enrutamiento de lectura/escritura (app, ORM y proxy), manejo del lag, monitoreo, failover y ajuste fino en PostgreSQL, MySQL y réplicas gestionadas en la nube.
RecipeConectar a PostgreSQL
Cómo conectar a bases de datos PostgreSQL en Python, JavaScript y Java.