PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Switchover/Switchback no Slony-I ao atualizar as versões principais do PostgreSQL 8.4.x/9.3.x

Cada nova versão do PostgreSQL vem com um pacote de recursos interessantes. Para beneficiar os novos recursos, o servidor de banco de dados deve ser atualizado. Escolher caminhos de atualização tradicionais como pg_dump/pg_restore ou pg_upgrade requer um tempo de inatividade significativo do aplicativo. Hoje, se você estiver procurando por um caminho de atualização de tempo de inatividade mínimo entre as principais versões do PostgreSQL com um plano de reversão perfeito, isso será realizado pela replicação assíncrona do Slony-I. Como o Slony-I (saiba mais sobre ele aqui) tem a capacidade de replicar facilmente entre diferentes versões do PostgreSQL, SO e arquiteturas de bits, então as atualizações são possíveis sem exigir um tempo de inatividade substancial. Além disso, possui uma funcionalidade consistente de alternância e retorno em seu design.

IMO, ao fazer as principais atualizações de versão, deve haver um plano de fallback adequado, porque, caso o aplicativo apresente bugs ou não funcione bem na versão atualizada, poderemos reverter para a versão mais antiga imediatamente. O Slony-I fornece essa funcionalidade na forma de switchback. Esta postagem demonstra a atualização de tempo de inatividade mínimo, incluindo etapas de alternância/retorno.

Antes de ir para a demonstração, um passo importante a ser observado, anteriormente à versão PG 9.0.x, as colunas de tipo de dados bytea usam para armazenar dados no formato ESCAPE e a versão posterior no formato HEX. Ao executar o switchback (versão mais recente para a versão mais antiga), esse tipo de diferença de formato bytea não é suportado pelo Slony-I, portanto, o formato ESCAPE deve ser mantido durante toda a duração da atualização, caso contrário, você poderá encontrar um erro:
ERROR  remoteWorkerThread_1_1: error at end of COPY IN: ERROR:  invalid input syntax for type bytea
CONTEXT: COPY sl_log_1, line 1: "1 991380 1 100001 public foo I 0 {id,500003,name,"A ",b,"\\x41"}"
ERROR remoteWorkerThread_1: SYNC aborted

Para corrigir, nenhuma alteração necessária no PG 8.4.x, mas no PG 9.3.5, o parâmetro bytea_output deve ser definido de HEX para ESCAPE, conforme mostrado. Podemos configurá-lo no nível do cluster ($PGDATA/postgresql.conf) ou no nível do usuário (ALTER TABLE…SET), preferi ir com alterações no nível do usuário.
slavedb=# alter user postgres set bytea_output to escape;
ALTER ROLE

Vamos prosseguir com as etapas de atualização. Abaixo estão os detalhes do meu servidor de duas versões usados ​​nesta demonstração, altere-os de acordo com a configuração do seu servidor, se você estiver tentando:
Origin Node (Master/Primary are called as Origin)                     Subscriber Node (Slave/Secondary are called as Subscriber)
------------------------------------------------- ----------------------------------------------------------
Host IP : 192.168.22.130 192.168.22.131
OS Version : RHEL 6.5 64 bit RHEL 6.5 64 bit
PG Version : 8.4.22 (5432 Port) 9.3.5 (5432 Port)
Slony Vers. : 2.2.2 2.2.2
PG Binaries : /usr/local/pg84/bin /opt/PostgreSQL/9.3/
Database : masterdb slavedb
PK Table : foo(id int primary key, name char(20), image bytea) ...restore PK tables structure from Origin...

Para compreensão simples e fácil implementação, dividi a demonstração em três seções
1. Compilando para binários Slony-I em versões do PostgreSQL
2. Criando scripts de replicação e executando
3. Testando a alternância/retorno.
1. Compilando para binários Slony-I contra a versão do PostgreSQL
Faça o download das fontes do Slony-I aqui e execute a instalação da fonte nos binários do PostgreSQL nos nós Origem e Assinante.
On Origin Node:
# tar -xvf slony1-2.2.2.tar.bz2
# cd slony1-2.2.2
./configure --with-pgbindir=/usr/local/pg84/bin
--with-pglibdir=/usr/local/pg84/lib
--with-pgincludedir=/usr/local/pg84/include
--with-pgpkglibdir=/usr/local/pg84/lib/postgresql
--with-pgincludeserverdir=/usr/local/pg84/include/postgresql/
make
make install

On Subscriber Node: (assuming PG 9.3.5 installed)
# tar -xvf slony1-2.2.2.tar.bz2
# cd slony1-2.2.2
./configure --with-pgconfigdir=/opt/PostgreSQL/9.3/bin
--with-pgbindir=/opt/PostgreSQL/9.3/bin
--with-pglibdir=/opt/PostgreSQL/9.3/lib
--with-pgincludedir=/opt/PostgreSQL/9.3/include
--with-pgpkglibdir=/opt/PostgreSQL/9.3/lib/postgresql
--with-pgincludeserverdir=/opt/PostgreSQL/9.3/include/postgresql/server/
--with-pgsharedir=/opt/PostgreSQL/9.3/share
make
make install

2. Criando scripts de replicação e executando
Para configurar a replicação, precisamos criar alguns scripts que cuidam da replicação, incluindo switchover/switchback.

1. initialize.slonik – Este script contém as informações de conexão dos nós Origem/Assinante.
2. create_set.slonik – Este script contém todas as Tabelas PK de Origem que replicam para o Nó do Assinante.
3. subscribe_set.slonik – Este script inicia a replicação de dados de conjuntos para o nó do assinante.
4. switchover.slonik – Este script ajuda a mover o controle da Origem para o Assinante.
5. switchback.slonik – Este script ajuda a reverter o controle do Assinante para a Origem.

Finalmente, mais dois scripts de inicialização “start_OriginNode.sh” e “start_SubscriberNode.sh” que inicia os processos slon de acordo com os binários compilados nos nós de origem/assinante.

Baixe todos os scripts aqui.

Aqui estão os dados de exemplo no Origin Node(8.4.22) na Foo Table com uma coluna de tipo de dados bytea, que iremos replicar para o Subscriber Node(9.3.5) com a ajuda dos scripts criados.
masterdb=# select * from foo;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
(3 rows)

Vamos chamar os scripts um por um para configurar a replicação. LEMBRE-SE QUE TODOS OS SCRIPT SLONIK DEVEM SER EXECUTADOS APENAS NO NÓ ORIGIN, EXCETO “start_OriginNode.sh” E “start_SubscriberNode.sh” QUE DEVEM SER EXECUTADOS INDIVIDUALMENTE.
-bash-4.1$ slonik initalize.slonik
-bash-4.1$ slonik create_set.slonik
create_set.slonik:13: Set 1 ...created
create_set.slonik:16: PKey table *** public.foo *** added.
-bash-4.1$ sh start_OriginNode.sh
-bash-4.1$ sh start_SubscriberNode.sh //ON SUBSCRIBER NODE
-bash-4.1$ slonik subscribe_set.slonik

Após a execução bem-sucedida do script acima, você pode notar que os dados em Origin(masterdb) foram replicados para Subscriber(slavedb). Também não permitindo nenhuma operação DML no nó do Assinante:
slavedb=# select * from foo;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
(3 rows)

slavedb=# insert into foo values (4,'PG-Experts','Image2');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

Legal… Nós movemos os dados para a versão mais recente do PostgreSQL 9.3.5. Nesse estágio, se você sentir que todos os dados foram replicados para o nó do assinante, poderá fazer a alternância.

3. Testando a alternância/retorno.

Vamos alternar para a versão mais recente com o script e tentar inserir dados nos nós de assinante/origem.
-bash-4.1$ slonik switchover.slonik
switchover.slonik:8: Set 1 has been moved from Node 1 to Node 2

slavedb=# insert into foo values (4,'PG-Experts','Image2');
INSERT 0 1

masterdb=# select * from foo ;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
4 | PG-Experts | Image2
(4 rows)

masterdb=# insert into foo values (5,'PG-Experts','Image3');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

Perfeito… Isto é o que estamos procurando, agora slavedb(Nó do Assinante) rodando a versão PG 9.3.5 aceitando dados e masterdb(Nó de Origem) recebendo os dados do slavedb. Também está rejeitando DMLs executados no masterdb.

O Slony-I Logs mostra os movimentos do ID do nó de origem/assinante no momento da alternância:
2014-12-12 04:55:06 PST CONFIG moveSet: set_id=1 old_origin=1 new_origin=2
2014-12-12 04:55:06 PST CONFIG storeListen: li_origin=1 li_receiver=2 li_provider=1
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: update provider configuration
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: helper thread for provider 1 terminated
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: disconnecting from data provider 1
...
...
2014-12-12 04:55:11 PST INFO start processing ACCEPT_SET
2014-12-12 04:55:11 PST INFO ACCEPT: set=1
2014-12-12 04:55:11 PST INFO ACCEPT: old origin=1
2014-12-12 04:55:11 PST INFO ACCEPT: new origin=2
2014-12-12 04:55:11 PST INFO ACCEPT: move set seq=5000006393
2014-12-12 04:55:11 PST INFO got parms ACCEPT_SET

Se você encontrar algum problema neste estágio, poderá voltar para a versão mais antiga. Após o retorno, você pode continuar com a versão mais antiga até que seu aplicativo ou outros problemas sejam corrigidos. Este é o plano de reversão perfeito sem perder muito tempo em caso de problemas após a transição.
-bash-4.1$ slonik switchback.slonik
switchback.slonik:8: Set 1 has been moved from Node 2 to Node 1

slavedb=# insert into foo values (5,'PG-Experts','Image3');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

masterdb=# insert into foo values (5,'PG-Experts','Image3');
INSERT 0 1

slavedb=# select * from foo ;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
4 | PG-Experts | Image2
5 | PG-Experts | Image3
(5 rows)

Muito agradável…!!! Esta não é a reversão exata com tempo de inatividade mínimo? Sim, é uma troca perfeita entre nós sem perder uma transação.

Logs mostrando o retorno do Assinante para o Nó de Origem:
2014-12-12 04:58:45 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1
2014-12-12 04:58:45 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: update provider configuration
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: helper thread for provider 2 terminated
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: disconnecting from data provider 2
2014-12-12 04:58:46 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
...
...
2014-12-12 04:58:47 PST INFO start processing ACCEPT_SET
2014-12-12 04:58:47 PST INFO ACCEPT: set=1
2014-12-12 04:58:47 PST INFO ACCEPT: old origin=2
2014-12-12 04:58:47 PST INFO ACCEPT: new origin=1
2014-12-12 04:58:47 PST INFO ACCEPT: move set seq=5000006403
2014-12-12 04:58:47 PST INFO got parms ACCEPT_SET
2014-12-12 04:58:48 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1

A essa altura, você deve ter notado que nenhuma das transações é perdida durante a operação de alternância entre as versões do PostgreSQL. Apenas o tempo de inatividade pode ser seu aplicativo para iniciar/parar para conectar-se aos nós Origem e Assinante, mas enquanto os nós Origem/Assinante nunca são removidos, eles estão apenas em execução.

Lembre-se, o método mostrado aqui não é útil apenas para atualizações, mas é o mesmo método no Slony-I para mover entre nós.

Obrigado pela sua paciência :). Espero que este post ajude você a atualizar o PostgreSQL com o mínimo de tempo de inatividade usando o Slony-I, incluindo um plano de reversão adequado.