Módulo 14 · Multinube: AWS y Google Cloud/Lección 91
Replicar datos entre AWS y Google Cloud
Replicación lógica de PostgreSQL, captura de cambios con Datastream y AWS DMS, copias de objetos, el RPO real entre proveedores y cómo evitar dos escritores.
⏱ 16 min
Al terminar podrás
- →Elegir un mecanismo para replicar una base relacional entre nubes
- →Copiar objetos y respaldos de S3 a Cloud Storage y al revés
- →Medir el RPO efectivo y el último punto consistente entre proveedores
- →Evitar split-brain y planear el failback entre nubes
Servicios de Google Cloud
Cloud SQL
AlloyDB
Datastream
Database Migration Service
Storage Transfer Service
Pub/Sub
Entre proveedores no hay un botón como Aurora Global Database. La replicación la armas tú con piezas estándar, y es asíncrona siempre: la distancia, el enlace y dos plataformas distintas lo garantizan. Eso significa que tu RPO entre nubes es el retraso de replicación del momento, y que tienes que medirlo, acotarlo y saber exactamente hasta dónde llegó la copia cuando decidas cambiar de proveedor.
Cuatro formas de replicar la base relacional
La base que mejor viaja es PostgreSQL estándar: RDS o Aurora PostgreSQL de un lado, Cloud SQL o AlloyDB del otro. Todos hablan el mismo protocolo de replicación lógica. Las opciones:
| Criterio | Replicación lógica nativa | |||
|---|---|---|---|---|
| Qué es | Publicaciones y suscripciones de PostgreSQL, sin servicios intermedios | Servicio de Google para migración continua hacia Cloud SQL o AlloyDB | Captura de cambios (CDC) con carga inicial, administrada por Google | Servicio de AWS para migración y CDC entre motores |
| Orígenes | Cualquier PostgreSQL 10 o superior con decodificación lógica activa | RDS, Aurora, Cloud SQL y PostgreSQL autoadministrado | PostgreSQL (incluidos RDS y Aurora), MySQL, Oracle, SQL Server y otros | Muchos motores; Cloud SQL para PostgreSQL es un origen documentado |
| Destinos | Otro PostgreSQL | Cloud SQL y AlloyDB | BigQuery y Cloud Storage; Cloud SQL o Spanner a través de Pub/Sub y Dataflow | RDS, Aurora o cualquier PostgreSQL alcanzable |
| Mecanismo | pgoutput y un slot por suscripción | pglogical en el origen, un slot por base | pgoutput, un slot por stream | test_decoding o pglogical |
| Para qué sirve | La copia de DR que puedes promover | Llevar la base a Google por primera vez | Copia analítica o flujo de eventos, no una base en espera | El sentido inverso: de Google hacia AWS, por ejemplo en el failback |
| Qué cuidar | No copia DDL ni el valor de las secuencias; las tablas necesitan clave primaria o identidad de réplica | Pensado para migrar: al promover termina. No acepta orígenes RDS con el extension pack de AWS SCT | Un slot abandonado acumula WAL hasta llenar el disco | Lo mismo que la replicación lógica, más la instancia de replicación que operas |
En la práctica, la copia de DR suele ser replicación lógica nativa: menos piezas, menos servicios que pueden fallar y control total del punto donde está la copia. Database Migration Service brilla en la carga inicial de una base grande. Para activarla del lado de AWS pones rds.logical_replication en 1 en el grupo de parámetros. En Cloud SQL, el lado que publica necesita el flag cloudsql.logical_decoding en on, y cambiarlo reinicia la instancia: actívalo desde el principio aunque hoy Cloud SQL solo sea suscriptor, porque lo necesitarás para el failback.
-- Publicador (Aurora PostgreSQL o RDS en AWS), con rds.logical_replication = 1
CREATE PUBLICATION pub_core FOR TABLE pedidos, pagos, clientes, outbox, heartbeat;
-- Suscriptor (Cloud SQL para PostgreSQL en Google Cloud), con un usuario cloudsqlsuperuser
CREATE SUBSCRIPTION sub_core
CONNECTION 'host=aurora-writer.aws.interno port=5432 dbname=app user=repl sslmode=verify-full password=...'
PUBLICATION pub_core;Una restricción que sorprende: la guía de Cloud SQL advierte que una instancia con alta disponibilidad no puede ser suscriptora porque no tiene una IP de salida constante. Revisa si aplica a tu topología de red antes de decidir el tamaño y la forma de la instancia secundaria; la alternativa es una instancia sin HA que se reconfigura al promoverla.
El RPO es el retraso, y se mide del otro lado
La replicación lógica envía solo transacciones confirmadas y en orden de commit. Por eso la secundaria siempre queda en un punto consistente: cada transacción está completa o ausente. Lo que necesitas saber es cuál es ese punto. Tres señales, cada una con su uso:
-- Primario: un latido que un job escribe cada 10 segundos
CREATE TABLE heartbeat (id int PRIMARY KEY, written_at timestamptz NOT NULL);
INSERT INTO heartbeat VALUES (1, now())
ON CONFLICT (id) DO UPDATE SET written_at = excluded.written_at;
-- Secundaria: el RPO efectivo, medido desde el otro lado
SELECT now() - written_at AS rpo_efectivo FROM heartbeat WHERE id = 1;
-- Primario: WAL que cada slot retiene porque el suscriptor aún no lo confirma
SELECT slot_name, active,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS pendiente
FROM pg_replication_slots WHERE slot_type = 'logical';
-- Secundaria: última posición del primario aplicada y cuándo
SELECT subname, latest_end_lsn, latest_end_time FROM pg_stat_subscription;Dos detalles honestos. El latido tiene un error de hasta N segundos (el intervalo del job) y depende de que los relojes de las dos nubes estén sincronizados; ambos proveedores sincronizan por NTP, pero súmale un margen. Y si la secundaria desaparece, el slot del primario retiene WAL para siempre: pon un tope con max_slot_wal_keep_size y una alarma sobre el tamaño retenido. El día del desastre, el último latido aplicado es tu evidencia: «la copia tiene todo lo confirmado hasta las 14:39:50».
Objetos y respaldos de un proveedor al otro
- De S3 a Cloud Storage: Storage Transfer Service tiene transferencias por eventos. Escucha las notificaciones de S3 en una cola de SQS y copia cada objeto nuevo o modificado casi en tiempo real, sin listar el bucket. Dos límites: el destino siempre es Cloud Storage y los borrados no se propagan. Para DR eso es bueno (un borrado accidental no cruza); para costos, programa una limpieza.
- De Cloud Storage a S3: AWS DataSync lee Cloud Storage por su API XML, autenticado con una llave HMAC. Esa llave sí es un secreto de larga duración: guárdala en Secrets Manager, dale permiso solo de lectura sobre el bucket y rótala.
- Respaldos de base de datos: un snapshot de RDS no se restaura en Cloud SQL ni al revés. Para tener un respaldo útil en la otra nube necesitas un formato portable, como un volcado lógico de
pg_dumpprogramado, copiado al otro proveedor. - Inmutabilidad en los dos lados: S3 Object Lock o AWS Backup Vault Lock en AWS; retención bloqueada en el bucket o bóvedas de Backup and DR con retención forzada en Google. Usa credenciales distintas para escribir y para administrar la retención. El detalle de cada lado está en respaldos inmutables y en datos en Google Cloud.
Mensajes y eventos: no hay cola entre nubes
SQS no replica hacia Pub/Sub ni al revés. Los mensajes en vuelo dentro de la cola del primario se pierden con él si no los diseñaste para reconstruirse. Tres técnicas lo resuelven juntas:
- 1
Outbox en la base
La transacción que guarda el pedido escribe también el evento en una tabla outbox. Un proceso aparte lo publica en SQS o Pub/Sub. Como la outbox viaja con la replicación de la base, la secundaria tiene los eventos que corresponden a sus datos, ni más ni menos. - 2
Consumidores idempotentes
Cada evento lleva un identificador único y el consumidor registra los que ya procesó. Así puedes reenviar sin efectos dobles. La técnica está en patrones de resiliencia. - 3
Reproducir desde un registro
Tras el cambio, el publicador de la secundaria reenvía la outbox desde un margen anterior al último punto consistente. Si usas Kafka, reproduces desde un offset; si archivas eventos en objetos, desde el archivo.
Un solo escritor: evitar el split-brain entre proveedores
Entre regiones de AWS hay endpoints globales y servicios que coordinan el cambio. Entre proveedores no hay nada que coordine por ti: si la base de AWS vuelve sola y la aplicación sigue escribiendo allí mientras Cloud SQL ya es primaria, tienes dos historias que nadie puede unir. Las defensas, en orden:
- 1
Un escritor por dato, siempre
Activo-activo para escrituras entre nubes no es una opción razonable para datos transaccionales. Lecturas en los dos lados, escrituras en uno. - 2
Congelar las escrituras
Pones la aplicación en modo solo lectura o detienes los procesos que escriben. Es preferible rechazar escrituras unos minutos que aceptarlas en dos lugares. - 3
Fencing: cambiar la cerradura de la sede caída
Revocas o rotas la credencial de la base en AWS, quitas la regla que permite conectar, escalas a cero los workers y sacas los registros DNS del primario. Todo desde afuera, porque quizá no puedas entrar a la nube caída. - 4
Un testigo fuera de las dos nubes
La decisión de quién es primario vive en un tercer lugar: un DNS externo con su propio control, un servicio de configuración en otra plataforma o, como mínimo, una persona con autoridad escrita. Ninguna nube aislada puede declararse primaria sola. - 5
Promover
Solo después de los pasos anteriores cortas la suscripción y abres las escrituras en Google Cloud.
-- En la secundaria, con las escrituras congeladas y el primario aislado
-- 1. Evidencia: el último punto aplicado
SELECT latest_end_lsn, latest_end_time FROM pg_stat_subscription WHERE subname = 'sub_core';
SELECT written_at FROM heartbeat WHERE id = 1;
-- 2. Corta la suscripción sin intentar borrar el slot remoto (el primario no responde)
ALTER SUBSCRIPTION sub_core DISABLE;
ALTER SUBSCRIPTION sub_core SET (slot_name = NONE);
DROP SUBSCRIPTION sub_core;
-- 3. Las secuencias no viajan con la replicación lógica: súbelas con margen
SELECT setval('pedidos_id_seq', (SELECT max(id) FROM pedidos) + 100000);El failback: replicar de vuelta y cambiar en una ventana
Volver a AWS es otro proyecto, igual que en failover y failback entre regiones, con más pasos manuales:
- Base nueva en AWS: la base vieja tiene datos divergentes. No la reconectes; crea una nueva y suscríbela a Cloud SQL (publicación en Cloud SQL, por eso el flag activado desde el día uno) o usa AWS DMS con Cloud SQL como origen.
- Reconciliar: lo que la base vieja confirmó después del último punto aplicado no está en la nueva historia. Extráelo de la base vieja, compáralo con los registros externos (pagos, correos enviados) y decide caso por caso. Los identificadores UUID evitan choques de llaves.
- Switchover planeado: en una ventana de poco tráfico, congelas, esperas a que el latido llegue al presente, comparas conteos y sumas de control por tabla, cambias el tráfico y reabres. Sin pérdida de datos y con un plan para revertir.
Las bases de la replicación síncrona y asíncrona están en replicación y consistencia, y la migración con CDC en migrar bases de datos. La red que todo esto necesita está en conectar AWS y Google Cloud.
Quiz
Pon a prueba lo que aprendiste
0 de 5 correctas · 5 sin responder
1.Necesitas una copia de Aurora PostgreSQL en Google Cloud que puedas promover como base primaria si AWS deja de estar disponible. ¿Qué mecanismo eliges?
2.El retraso de replicación entre AWS y Google suele ser de 3 segundos, pero en el cierre de mes sube a 4 minutos. El RPO acordado es de 1 minuto. ¿Cuál es la conclusión correcta?
3.Storage Transfer Service copia objetos de S3 a Cloud Storage por eventos. Alguien borra por error 10 000 objetos en S3. ¿Qué pasa en Cloud Storage?
4.AWS no responde y decides promover Cloud SQL. ¿Qué paso va antes de abrir las escrituras en Google?
5.Tras promover la secundaria en Google, los primeros pedidos fallan con «duplicate key» en la columna id. ¿Qué faltó?