Este documento descreve como configurar o fallback para o MySQL usando a replicação reversa. O fallback se refere a um plano de contingência para reverter ao banco de dados MySQL de origem se você encontrar problemas com o Spanner.
A replicação reversa é útil quando você encontra problemas inesperados e precisa fazer o fallback para o banco de dados MySQL original com o mínimo de interrupção no serviço. A replicação reversa permite fazer o fallback replicando os dados gravados no Spanner no banco de dados MySQL de origem.
O fluxo de replicação reversa envolve as seguintes etapas, executadas pelo
Spanner_to_SourceDb modelo do Dataflow:
Leia as mudanças do Spanner usando os fluxos de alterações do Spanner.
Filtre os registros usando o modo de filtragem
forward_migration.Transforme os dados do Spanner para que sejam compatíveis com o esquema do banco de dados de origem usando a ferramenta de migração do Spanner. Para mais informações, consulte Transformação personalizada.
Verifique se o banco de dados MySQL de origem já contém dados mais recentes para a chave primária especificada. Se dados mais recentes já existirem, o pipeline vai pular o evento de mudança para evitar a substituição de dados mais recentes.
Grave os dados no banco de dados de origem.
Usar o modelo do Dataflow Spanner_to_SourceDb
O modelo do Dataflow ajuda a garantir a consistência no nível da chave primária. O modelo cria tabelas de metadados, conhecidas como tabelas de sombra, no Spanner que contêm o carimbo de data/hora de confirmação da última transação de gravação no fragmento da tabela.
A gravação é consistente até o carimbo de data/hora de confirmação da chave primária.
A replicação reversa é executada como um job do Dataflow de streaming contínuo.
O job lê eventos de mudança dos fluxo de alterações do Spanner, os converte em tipos de dados compatíveis com o esquema do banco de dados de origem e os grava no banco de dados MySQL. Se um evento encontrar um erro temporário, o job vai tentar novamente de forma automática usando um diretório de fila de mensagens inativas (DLQ, na sigla em inglês) retry/ no Cloud Storage. Se um evento encontrar um erro permanente (ou exceder as tentativas), o job vai encaminhá-lo para um diretório de DLQ severe/ para resolução manual. Para mais informações sobre como resolver e reproduzir registros com falha,
consulte Monitorar e resolver erros de replicação reversa.
Antes de começar
Verifique a conectividade de rede entre o banco de dados MySQL de origem e o Google Cloud projeto em que os jobs do Dataflow são executados.
Permita os endereços IP do worker do Dataflow na instância do MySQL de origem.
Verifique se as credenciais do MySQL estão especificadas corretamente no
source shards file.Verifique se a instância do MySQL está on-line e em execução.
Verifique se o usuário do MySQL tem privilégios
INSERT,UPDATEeDELETEno banco de dados MySQL.Verifique se você tem as permissões do IAM necessárias para executar um modelo flexível do Dataflow. Para mais informações, consulte Criar e executar um modelo flexível.
Verifique se a porta
12345está aberta para comunicação entre as VMs de worker do Dataflow.
Funções exigidas
-
Para receber as permissões necessárias para iniciar a replicação reversa, peça ao administrador para conceder a você os seguintes papéis do IAM na instância:
- Usuário do banco de dados do Cloud Spanner (
roles/spanner.databaseUser) - Desenvolvedor do Dataflow (
roles/dataflow.developer)
- Usuário do banco de dados do Cloud Spanner (
-
Para garantir que a conta de serviço do Compute Engine tenha as permissões necessárias para iniciar a replicação reversa, peça ao administrador para conceder os seguintes papéis do IAM à conta de serviço do Compute Engine na instância:
- Usuário do banco de dados do Cloud Spanner (
roles/spanner.databaseUser) - Acessador de secrets do Secret Manager (
roles/secretmanager.secretAccessor) - Leitor do Secret Manager (
roles/secretmanager.viewer)
- Usuário do banco de dados do Cloud Spanner (
Executar a replicação reversa
Para executar a replicação reversa, siga estas etapas:
Faça upload do arquivo de sessão para o bucket do Cloud Storage.
Crie uma notificação do Pub/Sub para a pasta
retrydo diretório de DLQ. Para fazer isso, crie um tópico e uma assinatura do Pub/Sub para esse tópico.Crie e prepare o modelo do Dataflow. Para mais informações, consulte Criar um modelo.
Para iniciar o pipeline de streaming de replicação reversa, execute o seguinte comando
gcloud dataflow flex-template run:gcloud dataflow flex-template run "spanner-to-sourcedb-job" \ --project "PROJECT" \ --region "REGION" \ --template-file-gcs-location "TEMPLATE_SPEC_GCSPATH" \ --parameters "changeStreamName=CHANGE_STREAM_NAME" \ --parameters "instanceId=INSTANCE_ID" \ --parameters "databaseId=DATABASE_ID" \ --parameters "spannerProjectId=SPANNER_PROJECT_ID" \ --parameters "metadataInstance=METADATA_INSTANCE" \ --parameters "metadataDatabase=METADATA_DATABASE" \ --parameters "sourceShardsFilePath=SOURCE_SHARDS_FILE_PATH" \ # All flags after this point are optional [--parameters "startTimestamp=START_TIMESTAMP"] \ [--parameters "endTimestamp=END_TIMESTAMP"] \ [--parameters "shadowTablePrefix=SHADOW_TABLE_PREFIX"] \ [--parameters "sessionFilePath=SESSION_FILE_PATH"] \ [--parameters "filtrationMode=FILTRATION_MODE"] \ [--parameters "shardingCustomJarPath=SHARDING_CUSTOM_JAR_PATH"] \ [--parameters "shardingCustomClassName=SHARDING_CUSTOM_CLASS_NAME"] \ [--parameters "shardingCustomParameters=SHARDING_CUSTOM_PARAMETERS"] \ [--parameters "sourceDbTimezoneOffset=SOURCE_DB_TIMEZONE_OFFSET"] \ [--parameters "dlqGcsPubSubSubscription=DLQ_GCS_PUB_SUB_SUBSCRIPTION"] \ [--parameters "skipDirectoryName=SKIP_DIRECTORY_NAME"] \ [--parameters "maxShardConnections=MAX_SHARD_CONNECTIONS"] \ [--parameters "deadLetterQueueDirectory=DEAD_LETTER_QUEUE_DIRECTORY"] \ [--parameters "dlqMaxRetryCount=DLQ_MAX_RETRY_COUNT"] \ [--parameters "runMode=RUN_MODE"] \ [--parameters "dlqRetryMinutes=DLQ_RETRY_MINUTES"] \ [--parameters "sourceType=SOURCE_TYPE"] \ [--parameters "transformationJarPath=TRANSFORMATION_JAR_PATH"] \ [--parameters "transformationClassName=TRANSFORMATION_CLASS_NAME"] \ [--parameters "transformationCustomParameters=TRANSFORMATION_CUSTOM_PARAMETERS"] \ [--parameters "filterEventsDirectoryName=FILTER_EVENTS_DIRECTORY_NAME"]
As variáveis obrigatórias são descritas na lista a seguir:
PROJECT: o Google Cloud ID do projeto.REGION: a Google Cloud região em que você quer executar o job do Dataflow.TEMPLATE_SPEC_GCSPATH: o caminho do Cloud Storage para o arquivo de modelo do Dataflow preparado.CHANGE_STREAM_NAME: o nome do fluxo de alterações do Spanner que o job lê.INSTANCE_ID: o ID da instância do Spanner.DATABASE_ID: o ID do banco de dados do Spanner.SPANNER_PROJECT_ID: o ID do projeto em que as instâncias do Spanner estão localizadas.METADATA_INSTANCE: a instância do Spanner que armazena os metadados que o conector usa para controlar o consumo de dados da API de fluxo de alterações.METADATA_DATABASE: o banco de dados do Spanner que armazena os metadados que o conector usa para controlar o consumo de dados da API Change Stream.SOURCE_SHARDS_FILE_PATH: o caminho do Cloud Storage que contém as informações do perfil de conexão para os fragmentos de origem.
As variáveis opcionais são descritas na lista a seguir:
START_TIMESTAMP: o carimbo de data/hora a partir do qual as mudanças serão lidas. O padrão é vazio.END_TIMESTAMP: o carimbo de data/hora até o qual as mudanças serão lidas. Se não for especificado, o processo vai ler as mudanças indefinidamente. O padrão é vazio.SHADOW_TABLE_PREFIX: o prefixo para nomear tabelas de sombra. Padrão:shadow_.SESSION_FILE_PATH: o caminho para o arquivo de sessão no Cloud Storage que contém informações de mapeamento da ferramenta de migração do Spanner.FILTRATION_MODE: o modo que determina como filtrar registros com base em critérios. Os modos aceitos sãononeeforward_migration.SHARDING_CUSTOM_JAR_PATH: o local (caminho) no Cloud Storage do arquivo JAR personalizado que contém a lógica para buscar o ID do fragmento. O padrão é vazio.SHARDING_CUSTOM_CLASS_NAME: o nome de classe totalmente qualificado que tem a implementação personalizada do ID do fragmento. Esse parâmetro é obrigatório seSHARDING_CUSTOM_JAR_PATHfor especificado. O padrão é vazio.SHARDING_CUSTOM_PARAMETERS: uma string que contém os parâmetros personalizados a serem transmitidos para a classe de fragmentação personalizada. O padrão é vazio.SOURCE_DB_TIMEZONE_OFFSET: o ajuste de fuso horário do banco de dados de origem em relação ao UTC. Por exemplo,+10:00. Padrão:+00:00.DLQ_GCS_PUB_SUB_SUBSCRIPTION: a assinatura do Pub/Sub usada em uma política de notificação do Cloud Storage para o diretório de repetição de DLQ quando executado no modoregular. Especifique o nome no formatoprojects/<PROJECT_ID>/subscriptions/<SUBSCRIPTION_ID>. Quando você define esse parâmetro, o sistema ignoradeadLetterQueueDirectoryedlqRetryMinutes.SKIP_DIRECTORY_NAME: o diretório em que o sistema grava os registros que ele pula durante a replicação reversa. Padrão:skip.MAX_SHARD_CONNECTIONS: o número máximo de conexões permitidas por fragmento. Padrão:10000.DEAD_LETTER_QUEUE_DIRECTORY: o caminho para armazenar a saída da DLQ. O padrão é um diretório no local temporário do job do Dataflow.DLQ_MAX_RETRY_COUNT: o número máximo de vezes que o sistema tenta novamente erros temporários pela DLQ. Padrão:500.RUN_MODE: o tipo de modo de execução. As opções aceitas sãoregular,retryDLQeretryAllDLQ. UseretryDLQpara tentar novamente os registros de erro do diretóriosevere/ao lado de um pipeline ativo ouretryAllDLQpara processar os diretóriosretry/esevere/quando o pipeline normal estiver parado. Padrão:regular.DLQ_RETRY_MINUTES: o número de minutos entre as novas tentativas de DLQ. Padrão:10.SOURCE_TYPE: o tipo de banco de dados de origem para replicação reversa. Padrão:mysql.TRANSFORMATION_JAR_PATH: o local (caminho) no Cloud Storage do arquivo JAR personalizado que contém a lógica de transformação personalizada para processar registros na replicação reversa. O padrão é vazio.TRANSFORMATION_CLASS_NAME: o nome de classe totalmente qualificado que tem a lógica de transformação personalizada. Esse parâmetro é obrigatório seTRANSFORMATION_JAR_PATHfor especificado. O padrão é vazio.TRANSFORMATION_CUSTOM_PARAMETERS: uma string que contém os parâmetros personalizados a serem transmitidos para a classe de transformação personalizada. O padrão é vazio.FILTER_EVENTS_DIRECTORY_NAME: o diretório no Cloud Storage em que o sistema grava os registros que são filtrados pela lógica de transformação reversa personalizada. Padrão:filteredEvents.
Monitorar e resolver erros de replicação reversa
Ao executar a replicação reversa do Spanner para o MySQL, se o job do Dataflow de streaming não puder gravar um evento de mudança no banco de dados MySQL principal, ele vai classificar a falha em uma de duas categorias e gravar o registro em um diretório de fila de mensagens inativas no bucket do Cloud Storage:
- Erros repetíveis: falhas temporárias, como contenção de bloqueio do banco de dados MySQL
ou tempos limite de conexão de rede. O Dataflow grava esses eventos em um diretório de fila de mensagens inativas
retry/e tenta novamente de forma automática no mesmo pipeline até que sejam bem-sucedidos ou excedamdlqMaxRetryCount. - Erros graves: falhas permanentes que não podem ser resolvidas por novas tentativas automáticas,
como erros de conversão de tipo de dados, erros de sintaxe ou exceções
em JARs de transformação personalizados. O Dataflow grava esses eventos
em um diretório de fila de mensagens inativas
severe/(por exemplo,gs://MIGRATION_BUCKET/ENV/SERVICE/reverse/DB_SCHEMA/severe/) e incrementa o contador de usuários personalizadossevere_error_count.
Como erros graves não podem ser resolvidos por novas tentativas automáticas, o Dataflow remove esses eventos com falha do stream de replicação ativo e os salva no diretório severe/. Se não forem tratados, o banco de dados MySQL de reversão vai perder esses registros. Monitore regularmente o contador severe_error_count e o diretório severe/ durante a replicação reversa para resolver e reproduzir eventos de mudança com falha antes de iniciar uma reversão.
O contador personalizado do Dataflow severe_error_count é uma métrica cumulativa que registra o número total de erros graves encontrados desde que o job de streaming foi iniciado. Quando você reproduz e resolve registros com falha usando um job de repetição de DLQ, esse contador no pipeline de streaming original não diminui. Portanto, o diretório de DLQ grave do Cloud Storage (gs://MIGRATION_BUCKET/ENV/SERVICE/reverse/DB_SCHEMA/severe/) é a fonte confiável de verdade para saber se há erros não tratados.
Reproduzir registros com falha
Quando registros com falha aparecem no diretório de DLQ grave, inspecione os arquivos de erro JSON no Cloud Storage, identifique a causa raiz e resolva o problema subjacente.
Para reproduzir registros de DLQ corrigidos no MySQL, inicie um novo job do Dataflow usando um dos seguintes modos de execução:
- Modo
retryDLQ: execute esse modo como um job em lote ao lado do pipeline de streaming ativo para processar arquivos de erro no diretóriosevere/sem interromper a replicação reversa ativa. Execute esse modo depois de resolver as causas raiz dos erros graves. - Modo
retryAllDLQ: se o pipeline de streaming normal estiver parado, use esse modo para processar os diretóriosretry/esevere/. Não executeretryAllDLQsimultaneamente com um pipeline ativo, porque isso vai causar contenção de arquivos e conflitos de processamento.
Para iniciar um job de repetição de DLQ de replicação reversa usando a CLI gcloud, execute o seguinte comando:
gcloud dataflow flex-template run "spanner-to-sourcedb-retry-job" \
--project "PROJECT" \
--region "REGION" \
--template-file-gcs-location "TEMPLATE_SPEC_GCSPATH" \
--parameters "changeStreamName=CHANGE_STREAM_NAME" \
--parameters "instanceId=INSTANCE_ID" \
--parameters "databaseId=DATABASE_ID" \
--parameters "spannerProjectId=SPANNER_PROJECT_ID" \
--parameters "metadataInstance=METADATA_INSTANCE" \
--parameters "metadataDatabase=METADATA_DATABASE" \
--parameters "sourceShardsFilePath=SOURCE_SHARDS_FILE_PATH" \
--parameters "deadLetterQueueDirectory=DLQ_DIRECTORY" \
--parameters "runMode=retryDLQ"
Substitua:
PROJECT: o Google Cloud ID do projeto.REGION: a Google Cloud região em que você quer executar o job do Dataflow.TEMPLATE_SPEC_GCSPATH: o caminho do Cloud Storage para o arquivo de modelo do Dataflow preparado.CHANGE_STREAM_NAME: o nome do fluxo de alterações do Spanner que o job lê.INSTANCE_ID: o ID da instância do Spanner.DATABASE_ID: o ID do banco de dados do Spanner.SPANNER_PROJECT_ID: o ID do projeto em que as instâncias do Spanner estão localizadas.METADATA_INSTANCE: a instância do Spanner que armazena os metadados que o conector usa para controlar o consumo de dados da API de fluxo de alterações.METADATA_DATABASE: o banco de dados do Spanner que armazena os metadados que o conector usa para controlar o consumo de dados da API Change Stream.SOURCE_SHARDS_FILE_PATH: o caminho do Cloud Storage que contém as informações do perfil de conexão para os fragmentos de origem.DLQ_DIRECTORY: o caminho do Cloud Storage para o diretório de fila de mensagens inativas que contém os arquivos de erro graves a serem repetidos.