Nesta página, explicamos como configurar o failback para MySQL usando replicação inversa. O fallback se refere a um plano de contingência para reverter ao banco de dados MySQL de origem se houver problemas com o Spanner.
A replicação inversa é útil quando você encontra problemas inesperados e precisa fazer failback para o banco de dados MySQL original com interrupção mínima do serviço. Com a replicação inversa, é possível fazer um fallback replicando os dados gravados no Spanner para o banco de dados MySQL de origem. Isso garante que os dois bancos de dados sejam consistentes.
O fluxo de replicação inversa envolve as seguintes etapas, realizadas pelo
modelo do Dataflow Spanner_to_SourceDb:
Leia as mudanças do Spanner usando os fluxos de alterações do Spanner.
Verifique se 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 de origem já contém dados mais recentes para a chave primária especificada.
Grave os dados no banco de dados de origem.
Usar o modelo do Dataflow Spanner_to_SourceDb
O modelo do Dataflow garante 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 para essa tabela específica.
A gravação é consistente até o carimbo de data/hora de confirmação da chave primária.
É possível configurar o job do Dataflow que realiza a replicação inversa para ser executado em um dos seguintes modos:
Normal: esse é o modo padrão. O job do Dataflow lê eventos 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 aplica ao banco de dados de origem. O job repete automaticamente os erros. Depois de esgotar as novas tentativas, ele move os erros para a pasta
severedo diretório da fila de mensagens inativas (DLQ) no bucket do Cloud Storage. O job também move todos os erros permanentes para a pastasevere.RetryDLQ: nesse modo, o job do Dataflow lê eventos da pasta
severeda DLQ e tenta novamente. Execute esse modo depois de corrigir todos os erros permanentes. Esse modo lê apenas da DLQ, e não dos fluxo de alterações do Spanner. Se os registros processados da pastasevereforem movidos para a pastaretry, o job vai tentar de novo.
Antes de começar
Verifique se há conectividade de rede entre o banco de dados MySQL de origem e o projetoGoogle Cloud , em que os jobs do Dataflow serão executados.
Adicione os endereços IP dos workers do Dataflow à lista de permissões na instância de destino do MySQL.
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 inversa, 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 inversa, 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 inversa, 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 isso, crie um tópico do Pub/Sub e uma assinatura do Pub/Sub para esse tópico.Crie e organize o modelo do Dataflow. Para mais informações, consulte Modelo de criação.
Execute o modelo do Dataflow de replicação inversa usando o seguinte comando da Google Cloud CLI:
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" \ --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 ID do projeto do Google Cloud .region: a Google Cloud região.template-file-gcs-location: o caminho para o arquivo do Cloud Storage em que você preparou o modelo do Dataflow.changeStreamName: o nome do fluxo de alterações do Spanner que o job lê.instanceId: o ID da instância do Spanner.databaseId: o ID do banco de dados do Spanner.spannerProjectId: o ID do projeto em que suas instâncias do Spanner estão.metadataInstance: a instância que armazena os metadados usados pelo conector para controlar o consumo de dados da API Change Stream.metadataDatabase: o banco de dados que armazena os metadados usados pelo conector para controlar o consumo de dados da API Change Stream.sourceShardsFilePath: o caminho para o arquivo 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:
startTimestamp: o carimbo de data/hora a partir do qual começar a ler as mudanças. O padrão é vazio.endTimestamp: o carimbo de data/hora até o qual as mudanças serão lidas. Se você não fornecer um carimbo de data/hora, o processo vai ler as mudanças indefinidamente. O padrão é vazio.shadowTablePrefix: o prefixo para nomear tabelas de sombra. O padrão éshadow_.sessionFilePath: 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.filtrationMode: o modo que determina como filtrar registros com base em critérios. Os modos aceitos sãononeouforward_migration.shardingCustomJarPath: 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.shardingCustomClassName: o nome da classe totalmente qualificado que tem a implementação personalizada do ID de fragmento. Esse campo é obrigatório seshardingCustomJarPathfor especificado. O padrão é vazio.shardingCustomParameters: uma string que contém os parâmetros personalizados a serem transmitidos para a classe de fragmentação personalizada. O padrão é vazio.sourceDbTimezoneOffset: o ajuste do fuso horário em relação ao UTC para o banco de dados de origem. Exemplo: +10:00. Padrão: +00:00.dlqGcsPubSubSubscription: 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.skipDirectoryName: o diretório em que o sistema grava registros que são ignorados durante a replicação inversa. Padrão:skip.maxShardConnections: o número máximo de conexões permitidas por fragmento. Padrão: 10.000.deadLetterQueueDirectory: o caminho para armazenar a saída da DLQ. O padrão é um diretório no local temporário do job do Dataflow.dlqMaxRetryCount: o número máximo de vezes que o sistema tenta novamente erros temporários pela DLQ. Padrão: 500.runMode: o tipo de modo de execução. As opções sãoregularouretryDLQ. UseretryDLQpara repetir apenas os registros graves da DLQ. Padrão:regular.dlqRetryMinutes: o número de minutos entre as novas tentativas de DLQ. Padrão: 10.sourceType: o tipo de banco de dados de origem para fazer a replicação inversa. Padrão:mysql.transformationJarPath: 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 inversa. O padrão é vazio.transformationClassName: o nome de classe totalmente qualificado que tem a lógica de transformação personalizada. Este campo é obrigatório setransformationJarPathfor especificado. O padrão é vazio.transformationCustomParameters: uma string contendo os parâmetros personalizados que serão passados para a classe de transformação personalizada. O padrão é vazio.filterEventsDirectoryName: o diretório em que o sistema grava registros que são ignorados durante a replicação inversa. Padrão:skip.