Comutação e comutação por falha com a replicação pglogical

Selecione uma versão da documentação:

Esta página fornece informações sobre como fazer a comutação e a comutação por falha com a replicação pglogical.

Antes de começar

Depois de a replicação pglogical estar configurada e existir uma solução viável de alta disponibilidade (HA) e recuperação de desastres (DR), e reconhecendo que a replicação lógica não oferece true nem uma replicação abrangente de todos os objetos da base de dados, tem de testar esta configuração antes de começar a usá-la.

Para mais informações sobre a extensão pglogical, consulte o artigo Acerca da extensão pglogical.

Para informações sobre a replicação de dados com o pglogical, consulte os artigos Replique dados entre o AlloyDB para PostgreSQL e o AlloyDB Omni e Replique dados entre o AlloyDB Omni e outras bases de dados.

Comutação com replicação pglogical

A comutação é um processo controlado usado para comutar as funções entre as bases de dados do fornecedor e do subscritor. Quando faz uma comutação, as funções das duas bases de dados, fornecedor e subscritor, são invertidas. O fornecedor torna-se o subscritor e o subscritor torna-se o fornecedor.

Esta capacidade de comutação é importante para atualizações do sistema operativo, atualizações do PostgreSQL ou testes de comutação por falha.

Para o conseguir em configurações de replicação unidirecional, tem de configurar uma nova relação fornecedor/subscritor e remover a relação fornecedor/subscritor antiga.

Crie a nova configuração de fornecedor/subscritor

  1. Impeça a aplicação de escrever no sistema do fornecedor para evitar mais alterações à base de dados e verifique o atraso de replicação para garantir que todas as transações são repetidas no nó do subscritor:

    SELECT application_name,
        state,
        sync_state,
        client_addr,
        client_hostname,
        pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) AS sent_lag,
        pg_wal_lsn_diff(sent_lsn,flush_lsn) AS receiving_lag,
        pg_wal_lsn_diff(flush_lsn,replay_lsn) AS replay_lag,
        pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) AS total_lag,
        now()-reply_time AS reply_delay
    FROM pg_stat_replication
    ORDER BY client_hostname;
    

    Quando todos os campos de atraso apresentam zero, a replicação está atualizada e a base de dados está pronta para uma comutação.

    O resultado é semelhante ao seguinte:

    -[ RECORD 1 ]----+------------------------------
    application_name | test_sub_1
    state            | streaming
    sync_state       | async
    client_addr      | 10.45.0.80
    client_hostname  | 
    sent_lag         | 0
    receiving_lag    | 0
    replay_lag       | 0
    total_lag        | 0
    reply_delay      | 00:00:26.203433
    
  2. Converta a base de dados de subscritores numa base de dados de fornecedores:

    1. Interrompa a subscrição de subscritor existente.
    2. Adicione o conjunto de replicação, se necessário.
    3. Adicione as tabelas necessárias ao conjunto de replicação.
    4. Crie uma nova subscrição de subscritor na nova base de dados de subscritores.
    5. Redirecionar as candidaturas para o novo fornecedor.
  3. Interrompa a subscrição na base de dados de subscritores existente, que se torna o novo fornecedor:

    SELECT pglogical.alter_subscription_disable(SUBSCRIPTION_NAME);
    
  4. (Opcional) Crie um conjunto de replicação que corresponda à definição da base de dados do fornecedor original. Isto não é necessário se estiver a usar os conjuntos de replicação predefinidos:

    SELECT pglogical.create_replication_set(REPLICATION_SET_NAME);
    
  5. Adicione tabelas a esse conjunto de replicação:

    SELECT pglogical.replication_set_add_table(REPLICATION_SET_NAME, TABLE_NAME);
    

    Substitua o seguinte:

    • REPLICATION_SET_NAME: o nome do conjunto de replicação.
    • TABLE_NAME: o nome da tabela de um proprietário do esquema. Por exemplo, ARRAY['public'].`
  6. Na nova base de dados de subscritores, que era anteriormente a base de dados do fornecedor, crie a nova subscrição com a opção synchronize_data definida como false para impedir o carregamento inicial da tabela:

    SELECT pglogical.create_subscription (
               subscription_name := '<subscription name>',
               replication_sets := array['default'],
               synchronize_data := false,
               provider_dsn := 'host=<hostname or IP> port=5432 
               dbname=<db name> user=pglogical_replication password=<password>');
    
  7. Verifique se a subscrição está a funcionar no nó do fornecedor:

    SELECT application_name,
        state,
        sync_state,
        client_addr,
        client_hostname,
        pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) AS sent_lag,
        pg_wal_lsn_diff(sent_lsn,flush_lsn) AS receiving_lag,
        pg_wal_lsn_diff(flush_lsn,replay_lsn) AS replay_lag,
        pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) AS total_lag,
        now()-reply_time AS reply_delay
    FROM pg_stat_replication
    ORDER BY client_hostname;
    
  8. Se a replicação estiver a funcionar, altere as strings de ligação da aplicação para usar a base de dados do novo fornecedor e reinicie os níveis da aplicação.

Se alterar os dados no nó do fornecedor antigo após a paragem do subscritor, estas alterações não são replicadas e resultam na perda de dados. Se existirem alterações de dados não replicadas na base de dados do fornecedor original ou se o fornecedor original, que é o novo subscritor, não estiver num estado consistente com a base de dados do novo fornecedor, que é o antigo subscritor, tem de criar completamente a base de dados do novo subscritor.

Remova o fornecedor e a subscrição antigos

Se quiser uma replicação unidirecional, tem de remover a configuração antiga do fornecedor/subscritor.

  1. Remova a subscrição antiga no novo fornecedor:

    SELECT pglogical.drop_subscription('<subscription name>')
    
  2. Remova o conjunto de replicação no novo subscritor ou remova todas as tabelas do conjunto de replicação:

    SELECT pglogical.drop_replication_set('<replication set name>')
    
    SELECT pglogical.replication_set_remove_table('<replication set name>','<table name>')
    

Replicação bidirecional

Para mudar sem incorrer em tempo de inatividade ou para garantir que não são perdidos dados devido a alterações de dados não planeadas, tem de usar a replicação bidirecional. Quando implementar a replicação bidirecional, considere a resolução de conflitos, a menos que existam controlos rigorosos para impedir o acesso de escrita a ambos os nós ao mesmo tempo.

Pode configurar a configuração de resolução de conflitos através das seguintes pglogical.conflict_resolution definições:

  • error: a subscrição é interrompida quando é detetado um conflito.
  • apply_remote: aplicar sempre as alterações recebidas, independentemente dos dados na base de dados de subscritores. Esta é a predefinição.
  • keep_local: ignorar sempre os dados recebidos em conflito e rejeitar a alteração em conflito.
  • last_update_wins: a versão dos dados com a data/hora de confirmação mais recente é a versão dos dados confirmada
  • first_update_wins: a versão dos dados com a data/hora mais antiga é a versão dos dados que é confirmada

Para configurar a replicação bidirecional, configure o fornecedor e o subscritor de modo que a replicação ocorra em ambos os sentidos. O subscritor original também se torna um fornecedor com o mesmo conjunto de replicação que o fornecedor original. Consulte o artigo Crie uma tabela e adicione-a ao conjunto de replicação predefinido na base de dados do fornecedor do AlloyDB para PostgreSQL para criar um conjunto de replicação que duplique o conjunto de replicação original na base de dados do fornecedor inicial.

No fornecedor original, tem de adicionar um novo subscritor. Consulte o artigo Crie um nó e uma subscrição na base de dados de subscritores do AlloyDB Omni para criar um novo subscritor, garantindo que o parâmetro synchronize_data do comando pglogical.create_subscription está definido como false. Isto evita a cópia inicial dos dados da tabela.

Comutação por falha com replicação pglogical

A comutação por falha ocorre quando a base de dados do fornecedor fica indisponível por qualquer motivo e tem de mudar a aplicação para usar a base de dados do subscritor.

Para evitar que dados duplicados sejam aplicados acidentalmente à base de dados de subscritores de failover, tem de desativar a subscrição. Isto garante que as alterações de um fornecedor restaurado não são aplicadas por engano quando o fornecedor volta a ficar disponível.

  1. Pare o subscritor test_sub_1:

    SELECT pglogical.alter_subscription_disable(`test_sub_1`);
    
  2. Verifique se o estado está definido como disabled:

    SELECT pglogical.show_subscription_status('test_sub_1');
    

    O resultado é semelhante ao seguinte:

    show_subscription_status                                                                           
    ----------------------------------------------------------------------------
    (test_sub1,disabled,subscriber,"host=10.45.0.108 port=5432 dbname=my_test_db user=pglogical_replication",subscriber,{failover_set},{all})
    
  3. Verifique a palavra-chave desativada na saída do estado.

  4. Crie uma nova configuração de fornecedor/subscritor para manter a alta disponibilidade e a capacidade de recuperação de desastres.

  5. Crie um novo conjunto de replicação que contenha todas as tabelas que foram replicadas originalmente para que seja criado um novo subscritor quando a base de dados do fornecedor antiga for recuperada e convertida num novo subscritor ou for criado um novo subscritor.

  6. Configure o subscritor.

  7. Configure esta base de dados como o novo subscritor se conseguir recuperar a base de dados do fornecedor antigo até ao momento da falha. Use os mesmos passos para criar uma subscrição e defina o parâmetro synchronize_data para o comando pglogical.create_subscription como false para evitar a cópia inicial da tabela.

  8. Remova a configuração do fornecedor antiga no nó recuperado para evitar a acumulação de um ficheiro WAL.

  9. Se estiver a usar a base de dados do fornecedor antiga, elimine o conjunto de replicação completo ou remova todas as tabelas do conjunto de replicação uma a uma:

    SELECT pglogical.drop_replication_set('<replication set name>')
    
    SELECT pglogical.replication_set_remove_table('<replication set name>','<table name>')
    
  10. Mude a aplicação para escrever no novo nó.

O que se segue?