Tema 21: Replicación y alta disponibilidad — los calpixqui del altépetl
#PF-021 | XP: 320 | Insignia: Tlatoani de la Replica | Tier: Senior | Tiempo: 4.5 h

Objetivo
Configurarás replicación asíncrona en MySQL y PostgreSQL, aprenderás a promover un standby a primario, configurarás failover automático, y entenderás los patrones de alta disponibilidad (replicación, cluster, load balancing).
Mapa del tema
Visión mexica — Por Citlalli
El sistema tributario mexica tenía una pieza clave de resiliencia: el calpixqui que llevaba tributos a las provincias no viajaba solo. Iba con una escolta y llevaba un espejo del registro: una copia exacta del padron tributario que se quedaba en la provincia. Si el calpixqui moría en el camino, el espejo seguía en su destino. Si el registro del calmécac se dañaba, los espejos de las provincias permitían reconstruirlo.
La replicación de bases de datos es exactamente eso: el altépetl original (primario) mantiene espejos en otros altépetl (réplicas). Si el original cae, uno de los espejos se convierte en la nueva fuente. La diferencia con un simple respaldo: la réplica está viva, recibe cada transacción en tiempo real (o casi), y puede tomar el mando en segundos.
Bloque 1 — Conceptos: primaria, réplica, síncrona vs asíncrona
Términos clave
- Primaria (master): la base que recibe todas las escrituras.
- Réplica (standby/slave): copia que recibe los mismos cambios.
- Síncrona: la primaria espera confirmación de la réplica antes de confirmar al cliente. Más seguro, más lento.
- Asíncrona: la primaria no espera. Más rápido, pero si cae puedes perder datos recientes.
- Semi-síncrona: la primaria espera al menos una réplica, pero no todas. Balance.
Diagrama de replicación asíncrona
Cliente → INSERT → Primaria → [binlog/WAL] → Réplica
↓
ACK al cliente (no espera a la réplica)Diagrama de replicación síncrona
Cliente → INSERT → Primaria → [binlog/WAL] → Réplica
↓ ↓
ACK ←──────── ACK réplica ────┘
↓
ACK al clienteCuándo usar cada una
| Caso | Modo | Justificación | |---|---|---| | E-commerce, banca | Síncrona (o semi) | Cero pérdida tolerable | | Blog personal | Asíncrona | RPO de minutos es aceptable | | Analítica | Asíncrona con horas de retraso | No requiere datos en tiempo real | | Geo-redundancia | Asíncrona entre regiones | La latencia entre regiones haría la síncrona muy lenta |
Bloque 2 — Replicación en MySQL: binlog + relay log
Configurar el servidor primario
`my.cnf` en el primario:
[mysqld]
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
binlog_row_image = FULL
gtid_mode = ON
enforce_gtid_consistency = ONCrear usuario de replicación:
CREATE USER 'replica_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'Replica_2026!';
GRANT REPLICATION SLAVE ON . TO 'replica_user'@'%';
FLUSH PRIVILEGES;Configurar el servidor réplica
`my.cnf` en la réplica:
[mysqld]
server_id = 2
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
relay_log = /var/log/mysql/relay-bin.log
read_only = ON # Evita escrituras accidentalesTomar un snapshot del primario y restaurarlo en la réplica:
# En el primario
mysqldump -u root -p --single-transaction --triggers --routines --events \
--master-data=2 \
tienda_tlalli | gzip > /tmp/tienda_full.sql.gzCopiar al servidor réplica
scp /tmp/tienda_full.sql.gz replica:/tmp/En la réplica
gunzip -c /tmp/tienda_full.sql.gz | mysql -u root -pConfigurar la réplica para conectar al primario:
-- En la réplica
CHANGE MASTER TO
MASTER_HOST = '192.168.1.10',
MASTER_USER = 'replica_user',
MASTER_PASSWORD = 'Replica_2026!',
MASTER_AUTO_POSITION = 1; -- Usa GTIDSTART SLAVE;
Verificar:
SHOW SLAVE STATUS\G
-- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes
-- Seconds_Behind_Master: 0Probar la replicación
En el primario:
USE tienda_tlalli;
INSERT INTO resenas (cliente_id, producto_id, calificacion, comentario)
VALUES (1, 5, 5, 'Excelente cacao ceremonial');En la réplica:
SELECT FROM resenas ORDER BY resena_id DESC LIMIT 1;
-- Debe aparecer el nuevo registro en < 1 segundo (asíncrona)Promoción de réplica a primaria (failover manual)
Si el primario cae:
-- En la réplica
STOP SLAVE;
RESET SLAVE ALL;
SET GLOBAL read_only = OFF;Ahora la réplica acepta escrituras. Actualiza la configuración de la app para apuntar a la nueva IP.
Bloque 3 — Replicación en PostgreSQL: streaming replication
Configurar el servidor primario
`postgresql.conf`:
wal_level = replica
max_wal_senders = 3
wal_keep_size = '1GB'`pg_hba.conf`:
# Permitir réplica desde la IP de la réplica
host replication replica_user 192.168.1.20/32 scram-sha-256CREATE ROLE replica_user WITH LOGIN REPLICATION PASSWORD 'Replica_2026!';Configurar el servidor réplica
Tomar un backup base con `pg_basebackup`:
pg_basebackup -U replica_user -h 192.168.1.10 \
-D /var/lib/postgresql/16/main -Fp -Xs -PCrear archivo `standby.signal`:
touch /var/lib/postgresql/16/main/standby.signal`postgresql.conf` en la réplica:
primary_conninfo = 'host=192.168.1.10 port=5432 user=replica_user password=Replica_2026!'
promote_trigger_file = '/tmp/promote_to_primary' # Failover manualIniciar PostgreSQL en modo standby:
sudo systemctl start postgresqlVerificar:
SELECT FROM pg_stat_replication;
-- En el primario, debe mostrar la réplica conectada-- En la réplica
SELECT pg_is_in_recovery();
-- Esperado: t (true)
Failover manual (switchover)
# En la réplica
touch /tmp/promote_to_primary
O explícitamente:
pg_ctl promote -D /var/lib/postgresql/16/mainVerificar:
SELECT pg_is_in_recovery();
-- Esperado: f (false, ahora es primaria)Failover automático con Patroni
Patroni es la opción más usada para HA en PostgreSQL. Combina:
- Replicación streaming.
- Etcd/Zookeeper para consenso de quién es el primario.
- VIP (IP virtual) que se mueve al nuevo primario.
- Reinicio automático del PostgreSQL si falla.
[App] → [HAProxy] → [Patroni + PostgreSQL #1] ⇄ [Patroni + PostgreSQL #2]
↑ ↑
└── [Etcd cluster] ─────────────┘Patroni se encarga de:
- Detectar falla del primario.
- Promover la réplica con menos lag.
- Mover la VIP.
- Actualizar HAProxy para enviar tráfico al nuevo primario.
Bloque 4 — Failover manual y automático
Switchover planeado (ej. mantenimiento del primario)
Failover de emergencia (el primario se cayó)
Pre-flight checks antes de promover
- Lag de la réplica: ¿está al día? Si hay lag de horas, perderás esas horas de datos.
- Conexiones activas: ¿hay queries en curso en el primario caído?
- WALs pendientes: ¿hay WALs en el primario que no se enviaron a la réplica?
-- En la réplica, ver el último WAL recibido
SELECT pg_last_wal_receive_lsn();
SELECT pg_last_wal_replay_lsn();
-- Si difieren, hay WALs pendientesBloque 5 — Patrones de alta disponibilidad
Patrón 1: Réplica de lectura (read replica)
[App writes] → [Primaria]
[App reads] → [Réplica 1, Réplica 2, Réplica 3]- La primaria maneja todas las escrituras.
- Las réplicas manejan lecturas (reportes, dashboards, búsquedas).
- Reduce carga en la primaria.
Patrón 2: Hot standby + failover automático
[App] → [HAProxy] → [Primaria] ⇄ [Standby]
↑
[Patroni + etcd]- Una réplica que puede tomar el mando en 30 segundos.
- Útil para e-commerce, banca.
Patrón 3: Multi-región
[App región A] → [Primaria A] ⇄ [Réplica B] (en otra región)
↓
[Réplica A'] (lectura local en A)- Protección contra caída de toda una región (terremoto, corte de energía masivo).
- Latencia entre regiones hace que la replicación sea asíncrona.
- RPO puede ser de minutos.
Patrón 4: Cluster (Galera Cluster para MySQL)
[App] → [Nodo 1] ⇄ [Nodo 2] ⇄ [Nodo 3]- Todos los nodos aceptan lecturas y escrituras.
- Consenso síncrono (certification-based).
- Latencia de commit mayor que replicación asíncrona.
- Útil cuando necesitas geolocalización de escrituras.
Patrón 5: Cloud-managed (AWS RDS Multi-AZ, Aurora, etc.)
- El proveedor maneja replicación, failover, backups.
- Failover de RDS Multi-AZ: 60-120 segundos.
- Costo mayor pero menos operación.
AI Mission
Pídele a tu IA que diseñe la arquitectura HA para tu caso. Prompt sugerido:
Tengo una base de datos MySQL 8 con 50 GB de datos, 500 escrituras/segundo
pico, 5000 lecturas/segundo, RPO objetivo de 5 minutos, RTO de 1 minuto,
presupuesto de $200 USD/mes en infraestructura.Dame:
Diagrama de la arquitectura HA que cumpla RPO y RTO.
Proveedor cloud recomendado (AWS, GCP, Azure, DigitalOcean).
Estimación de costo mensual.
Procedimiento de failover documentado en 5 pasos.
Riesgos que no se cubren con esta arquitectura.
Aplica la recomendación, pero verifica los costos en la página del proveedor antes de decidir. La IA puede subestimar o sobreestimar según su entrenamiento.Errores típicos
LAB práctico — Configurar primario y standby
Objetivo: levantar un primario y una réplica asíncrona en MySQL o PostgreSQL, verificar que la replicación funciona, y practicar el failover manual.
Opción A: MySQL con dos instancias en la misma máquina
# Crear segundo datadir
sudo mysql_install_db --datadir=/var/lib/mysql-replica --user=mysqlInicializar con configuración distinta
sudo nano /etc/mysql/replica.cnf[mysqld]
port = 3307
datadir = /var/lib/mysql-replica
server_id = 2
log_bin = /var/log/mysql-replica/mysql-bin.log
read_only = ONsudo chown -R mysql:mysql /var/lib/mysql-replica /var/log/mysql-replica
sudo mysqld --defaults-file=/etc/mysql/replica.cnf &Opción B: PostgreSQL con `pg_basebackup`
(Ver Bloque 3.)
Paso 2 — Configurar la replicación
MySQL:
-- En el primario
CREATE USER 'replica_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'Replica_2026!';
GRANT REPLICATION SLAVE ON . TO 'replica_user'@'%';
FLUSH PRIVILEGES;-- Snapshot
mysqldump -u root -p --single-transaction --master-data=2 tienda_tlalli > /tmp/tienda.sql
-- En la réplica
mysql -u root -p -P 3307 -e "CREATE DATABASE tienda_tlalli;"
mysql -u root -p -P 3307 tienda_tlalli < /tmp/tienda.sql
CHANGE MASTER TO
MASTER_HOST = '127.0.0.1',
MASTER_PORT = 3306,
MASTER_USER = 'replica_user',
MASTER_PASSWORD = 'Replica_2026!',
MASTER_AUTO_POSITION = 1;
START SLAVE;
SHOW SLAVE STATUS\G
PostgreSQL:
pg_basebackup -U replica_user -h 127.0.0.1 \
-D /var/lib/postgresql/16-replica -Fp -Xs -Ptouch /var/lib/postgresql/16-replica/standby.signal
echo "primary_conninfo = 'host=127.0.0.1 port=5432 user=replica_user password=Replica_2026!'" \
>> /var/lib/postgresql/16-replica/postgresql.conf
Paso 3 — Probar
-- En el primario: insertar
INSERT INTO resenas (cliente_id, producto_id, calificacion, comentario)
VALUES (1, 1, 5, 'Replica funciona');-- En la réplica: verificar
SELECT * FROM resenas ORDER BY resena_id DESC LIMIT 1;
-- Debe aparecerPaso 4 — Failover manual
MySQL:
-- En la réplica
STOP SLAVE;
RESET SLAVE ALL;
SET GLOBAL read_only = OFF;PostgreSQL:
pg_ctl promote -D /var/lib/postgresql/16-replicaPaso 5 — Verificar que la nueva primaria acepta escrituras
INSERT INTO resenas (...) VALUES (...);
-- Debe funcionarEntregables del LAB
- [ ] Réplica conectada y replicando (`Seconds_Behind_Master = 0`).
- [ ] Inserción en primario visible en réplica en < 5 segundos.
- [ ] Failover manual ejecutado exitosamente.
- [ ] Antigua primaria reconectada como nueva réplica (opcional).
- [ ] Documento `REPLICACION.md` con la arquitectura, comandos, y procedimiento de failover.
Quest
Preguntas de opción múltiple (10)
1. ¿Qué es una réplica asíncrona?
A. La primaria espera confirmación de la réplica antes de hacer commit. B. La primaria no espera a la réplica; puede haber pequeña pérdida de datos en failover. C. Las réplicas escriben a la primaria. D. No existe ese concepto.
2. ¿Qué archivo se usa para activar el modo standby en PostgreSQL?
A. `postgresql.conf` B. `recovery.conf` C. `standby.signal` D. `pg_hba.conf`
3. ¿Qué hace `read_only = ON` en MySQL?
A. Impide lecturas. B. Impide escrituras (excepto las de usuarios con SUPER). C. Activa la réplica. D. Cambia el charset.
4. ¿Qué herramienta automatiza el failover en PostgreSQL?
A. pg_dump. B. Patroni. C. psql. D. pg_basebackup.
5. ¿Qué variable MySQL muestra el atraso de la réplica?
A. `Slave_Lag` B. `Seconds_Behind_Master` C. `Replica_Delay` D. `Read_Lag`
6. ¿Qué es RPO?
A. Recovery Point Objective: pérdida de datos tolerable. B. Recovery Process Order. C. Read Parallel Operations. D. Relational Performance Optimizer.
7. ¿Qué es RTO?
A. Recovery Time Objective: tiempo de inactividad tolerable. B. Real-Time Operations. C. Read Through Output. D. Relational Table Optimization.
8. ¿Qué hace `pg_basebackup`?
A. Respaldo lógico. B. Respaldo físico base mientras la base sigue corriendo. C. Borra la base. D. Activa la réplica.
9. ¿Qué modo de replicación tiene mayor latencia de commit?
A. Asíncrona. B. Síncrona. C. Semi-síncrona. D. Ninguna.
10. ¿Por qué es importante monitorear el lag de la réplica?
A. Para hacer la base más rápida. B. Para saber cuántos datos se perderían en un failover. C. Para ahorrar CPU. D. No es importante.
Preguntas abiertas (3)
A. Explica la diferencia entre replicación síncrona y asíncrona. ¿Cuándo usarías cada una en un sistema de e-commerce?
B. Tu primaria se cayó y necesitas hacer failover manual. Lista los 5 pasos en orden y los riesgos de cada uno.
C. Compara Galera Cluster con replicación asíncrona de MySQL. Para una startup con 10K usuarios concurrentes, ¿cuál elegirías y por qué?
Respuestas modelo
1. B — Asíncrona = la primaria no espera. La A es síncrona. La C es absurdo. La D es falsa.
2. C — `standby.signal`. La A es config. La B ya no se usa. La D es autenticación.
3. B — `read_only = ON` impide escrituras a usuarios normales. La A es lo contrario. La C no es lo que hace. La D es charset.
4. B — Patroni. La A es respaldo. La C es cliente. La D es backup.
5. B — `Seconds_Behind_Master`. La A, C, D no existen.
6. A — RPO = Recovery Point Objective. La B, C, D son ficticias.
7. A — RTO = Recovery Time Objective. La B, C, D son ficticias.
8. B — `pg_basebackup` = respaldo físico base en línea. La A es `pg_dump`. La C es `DROP`. La D es configuración manual.
9. B — Síncrona espera ACK de la réplica, mayor latencia. La A es la más rápida. La C es balance. La D no aplica.
10. B — Para saber la pérdida de datos en failover. La A no es su propósito. La C no es cierto. La D es falsa.
Respuestas a las preguntas abiertas
A. Síncrona: la primaria espera confirmación de la réplica antes de retornar al cliente. Cero pérdida de datos, pero mayor latencia de commit. Asíncrona: la primaria no espera, puede haber pérdida si la primaria cae antes de enviar los cambios. Para e-commerce, síncrona o semi-síncrona es preferible para datos críticos (pedidos, pagos); asíncrona para datos secundarios (logs, métricas).
B. Cinco pasos:
C. Para una startup con 10K usuarios concurrentes: Galera Cluster si necesitas geolocalización de escrituras o alta disponibilidad inmediata; replicación asíncrona si la mayoría son lecturas y un failover de 30 segundos es aceptable. Galera tiene mayor latencia de commit y requiere al menos 3 nodos (quorum). Para una startup, RDS Multi-AZ (cloud managed) suele ser la opción más pragmática: el proveedor maneja la replicación y failover.
Tras las huellas — Por Citlalli
El sistema de calpixqui que llevaban tributos a las provincias tenía un detalle brillante: si un calpixqui no llegaba a su destino en 20 días, otro partía con una copia del registro. No esperaban a confirmar que el primero había llegado. Esa es la esencia de la replicación asíncrona con múltiples destinos: el sistema sigue funcionando aunque una pieza falle.
La diferencia con los mexicas es que hoy no esperamos 20 días. Con la replicación moderna, los espejos se actualizan en segundos, y la pérdida tolerable de una réplica se mide en segundos también. Pero el principio es el mismo: múltiples copias, destinos distribuidos, failover automático cuando un camino falla.
Sabiduría mexica: no confíes en un solo camino. Siempre ten un espejo, y otro, y otro.