Saltar al contenido
aprendeaws.dev

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:

CriterioReplicación lógica nativaDatabase Migration ServiceDatastreamAWS DMS
Qué esPublicaciones y suscripciones de PostgreSQL, sin servicios intermediosServicio de Google para migración continua hacia Cloud SQL o AlloyDBCaptura de cambios (CDC) con carga inicial, administrada por GoogleServicio de AWS para migración y CDC entre motores
OrígenesCualquier PostgreSQL 10 o superior con decodificación lógica activaRDS, Aurora, Cloud SQL y PostgreSQL autoadministradoPostgreSQL (incluidos RDS y Aurora), MySQL, Oracle, SQL Server y otrosMuchos motores; Cloud SQL para PostgreSQL es un origen documentado
DestinosOtro PostgreSQLCloud SQL y AlloyDBBigQuery y Cloud Storage; Cloud SQL o Spanner a través de Pub/Sub y DataflowRDS, Aurora o cualquier PostgreSQL alcanzable
Mecanismopgoutput y un slot por suscripciónpglogical en el origen, un slot por basepgoutput, un slot por streamtest_decoding o pglogical
Para qué sirveLa copia de DR que puedes promoverLlevar la base a Google por primera vezCopia analítica o flujo de eventos, no una base en esperaEl sentido inverso: de Google hacia AWS, por ejemplo en el failback
Qué cuidarNo copia DDL ni el valor de las secuencias; las tablas necesitan clave primaria o identidad de réplicaPensado para migrar: al promover termina. No acepta orígenes RDS con el extension pack de AWS SCTUn slot abandonado acumula WAL hasta llenar el discoLo 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:

SeñalQué te dice
Posición del log (LSN)Hasta qué byte del WAL del primario aplicó la secundariapg_stat_subscription en el suscriptor y confirmed_flush_lsn en el slot del publicador. Exacto, pero no dice tiempo
Tabla de latidoHasta qué hora del primario llegó la copiaUn job escribe now() cada N segundos; la secundaria lo lee. Es el RPO efectivo en minutos y segundos
Tamaño retenido por el slotCuánto WAL espera a la secundariaSi crece sin parar, la réplica está caída o no da abasto, y el disco del primario se llena
-- 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_dump programado, 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 4.AWS no responde y decides promover Cloud SQL. ¿Qué paso va antes de abrir las escrituras en Google?

  5. 5.Tras promover la secundaria en Google, los primeros pedidos fallan con «duplicate key» en la columna id. ¿Qué faltó?