segunda-feira, 11 de outubro de 2010

Configurando Replicação Nativa do Postgres 9.0 no Slackware 13.0

Uma das grandes vantagens no Postgres 9.0 é a replicação nativa, assíncrona, baseada no log de transação (WAL-LOG), usando Hot Standby
e Stream Replication (Prontidão a Quente e Fluxo de Replicação), neste artigo irei descrever como configurar três servidores com IPs
distintos e com Linux Slackware 13 rodando o Postgres 9.0 replicado, sendo 1 Master como escrita e leitura e 2 Slaves (replicado)
apenas com leitura, mas podendo ser executados consultas.

Se você usa o pgAdmin III atualize para versão 1.12.0 ou superior, pois o acesso ao Postgres 9.0 com este client só é possível a partir
desta versão.

Se não tiver servidores com fartura, ou um cluster para testar, você pode simular as máquinas com IPs distintos na rede, usei o Oracle
Virtual Box versão 3.2.6 com as placas de redes configuradas para modo bridge, não esqueça de adaptar os seus IPs conforme a estrutura
da sua rede.

Iremos instalar o Postgres 9.0, mais exatamente a versão 9.0.5, tomando por base o código fonte, isto é, iremos baixar, desempacotar e
compilar e instalar e depois configurar.

No servidor Master (ip: 10.3.128.1):

Baixar o Postgres 9.0 na pasta logado com usuário root:

#/usr/local

#wget http://ftp.postgresql.org/pub/source/v9.0.5/postgresql-9.0.5.tar.gz


Em seguida ainda logado com o usuário root:

#cd /usr/local

#cp /root/postgresql-9.0.5.tar.gz .

#tar -zxvf postgresql-9.0.5.tar.gz

#cd postgresql-9.0.5

#./configure

#gmake

#su

#gmake install

#adduser postgres

#mkdir /usr/local/pgsql/data

#chown postgres /usr/local/pgsql/data

$su – postgres

$/usr/local/pgsql/bin/initdb –D /usr/local/pgsql/data

$/usr/local/pgsql/bin/postgres –D /usr/local/pgsql/data >logfile 2>&1 &

$/usr/local/pgsql/bin/createdb test

$/usr/local/pgsql/bin/psql test

$exit


Nos servidores Slaves (ip: 10.3.128.2 e ip:10.3.128.3):

Mesmo terêtêtê do Master descrito anteriormente...

Até aqui foi instalado o Postgres no modo padrão nas três máquinas, porem ainda faltam alguns detalhes como arquivo padrão de inicialização,
habilitar o Linux ao reiniciar carregando o Postgres automaticamente, para isso iremos executar os comandos abaixo nas três máquinas servidoras:

#cp /usr/local/postgresql-9.0.5/contrib/start-scripts/linux /etc/rc.d/rc.pgsqld 

#chmod 755 /etc/rc.d/rc.pgsqld 

#./etc/rc.d/rc.pgsqld stop 

#./etc/rc.d/rc.pgsqld start

#echo "

# Start the PostgreSQL database: 

if [ -x /etc/rc.d/rc.pgsqld ]; then 

  . /etc/rc.d/rc.pgsqld start

fi " >> rc.M

#reboot 



Instalamos o Postgres em sua forma básica no Linux com a porta padrão 5432, nos três servidores, agora vamos configurar uma pasta compartilhada
NFS (Network File System) na máquina MASTER para que os SLAVES copiem WAL LOG desta pasta, não levei em consideração a segurança, na configuração
do NFS, mas você pode logo que usar essa receita de bolo, fazer uma ajuste fino no NFS, para tanto basta pedir uma ajudinha ao Google,
digitando: segurança nfs

Criando a pasta para replicação na máquina MASTER:

#mkdir /home/postgres/replication

#chown postgres /home/postgres/replication


Configurando o NFS:

No servidor Master (ip: 10.3.128.1)

#echo "

/home/postgres/replication 10.3.128.1(rw,subtree_check,no_root_squash,sync)

/home/postgres/replication 10.3.128.2(rw,subtree_check,no_root_squash,sync)

/home/postgres/replication 10.3.128.3(rw,subtree_check,no_root_squash,sync)

" >> /etc/exports

#echo " 

ALL: ALL@ALL

" >> /etc/hosts.deny

#echo " 

ALL : ALL@10.3.128.2 : ALLOW

ALL : ALL@10.3.128.3 : ALLOW

" >> /etc/hosts.allow

#chmod 755 /etc/rc.d/rc.rpc

#chmod 755 /etc/rc.d/rc.nfsd

#. /etc/rc.d/rc.rpc start

#. /etc/rc.d/rc.nfsd start

#exportfs -a

#rpcinfo –p 

#showmount –e localhost

#mkdir /mnt/postgres

#mount –t nfs 10.3.128.1:/home/postgres/replication /mnt/postgres

#mount 



Nos servidores Slaves (ip: 10.3.128.2 e ip:10.3.128.3):

#chmod 755 /etc/rc.d/rc.rpc

#chmod 755 /etc/rc.d/rc.nfsd

#. /etc/rc.d/rc.rpc start

#. /etc/rc.d/rc.nfsd start

#rpcinfo –p 

#showmount –e 10.3.128.1

#mkdir /mnt/postgres

#mount –t nfs 10.3.128.1:/home/postgres/replication /mnt/postgres



Pronto até aqui configuramos o NFS para que os SLAVES copiem WAL-LOG do MASTER; agora iremos realmente fazer a replicação.

No servidor Master (ip: 10.3.128.1): (por segurança vamos fazer uma cópia de postgresql.conf e pg_hba.conf)

#cp /usr/local/pgsql/data/postgresql.conf  /usr/local/pgsql/data/postgresql.conf.backup

#cp /usr/local/pgsql/data/pg_hba.conf /usr/local/pgsql/data/pg_hba.conf.backup
 
#echo "

listen_addresses = '*'

port = 5432

wal_level = hot_standby

archive_mode = on

archive_command = 'cp %p /home/postgres/replication/%f'

max_wal_senders = 2

#wal_sender_delay  = 200ms

wal_keep_segments = 20

" >> /usr/local/pgsql/data/postgresql.conf

#echo "

host replication all 0.0.0.0/0 trust

" >> /usr/local/pgsql/data/pg_hba.conf

#. /etc/rc.d/rc.pgsqld restart


Alguns comentários sobre o terêtêtê acima:

No postgresql.conf:

Os parâmetros: listem_address = '*' , port = 5432 habilitam qualquer maquina externa acessar com a porta mencionada.

O parâmetro: wal_level = hot_standby habilita a servidor para replicação, Master.

O parâmetro: max_wal_senders = 2 habilita dois servidores Slaves a conectarem ao Master.

O parâmetro: archive_command = 'cp %p /home/postgres/replication/%f' copia os arquivos WAL-LOG, para um diretório distinto.

O parâmetro: #wal_sender_delay = 200ms define o interervalo entre as operações de envio de fragamentos (stream)
pelo processo WALSENDER. Padrão: 200 ms.

O parâmetro: wal_keep_segments = 20 define número de arquivos de log que devem ser mantidos para recuperação em caso de problemas
com restauração automática

No arquivo pg_hba.conf:

O parâmetro: host replication all 0.0.0.0/0 trust habilita qualquer máquina a acessar o master para replicação,
isso pode ser restringido para apenas os ips dos Slaves.

Se tudo ocorreu bem, o servidor Master (ip: 10.3.128.1) com banco test está em condições de acesso, use o seguinte comando:

#/usr/local/bin/psql –d test

Outra forma de monitorar, o que está acontecendo com servidor Master é vendo os logs de Postgres, conforme exemplo abaixo:

#tail –f /usr/local/pgsql/data/serverlog


No servidor Master (ip: 10.3.128.1)

Iniciando o backup do Master para os para os Slaves...

usr/local/data/pgsql/bin/psql –d postgres -c "SELECT pg_start_backup('ok');"


Nos servidores Slaves (ip: 10.3.128.2 e ip:10.3.128.3):

Copiando o diretório data do servidor Master para os Slaves e removendo o pg_xlog (WAL-LOG) e o arquivo postmaster.pid dos Slaves

#scp 10.3.128.1:/usr/local/pgsql/data/* /usr/local/pgsql/data

#rm -f /usr/local/pgsql/data/pg_xlog/*

#rm /usr/local/pgsql/data/postmaster.pid


Como copiamos o diretório data do Master para os Slaves, vamos pegar o backup postgresql.conf.backup e pg_hba.conf.backup
feito anteriormente no Master e aproveitar nos Slaves:

Ainda nos servidores Slaves (ip: 10.3.128.2 e ip:10.3.128.3) com instancias paradas do Postgres:

#cp /usr/local/pgsql/data/postgresql.conf.backup  /usr/local/pgsql/data/postgresql.conf

#cp /usr/local/pgsql/data/pg_hba.conf.backup /usr/local/pgsql/data/pg_hba.conf

#echo "

listen_addresses = '*'

port = 5432

wal_level = minimal

archive_mode = off

hot_standby = on 

" >> /usr/local/pgsql/data/postgresql.conf


#echo "

standby_mode = 'on'

primary_conninfo = 'host=10.3.128.1 port=5432 user=postgres password=postgres'

restore_command = 'cp /mnt/postgres/%f %p'

trigger_file = '/tmp/trigger.pgsql.5432'

" > /usr/local/pgsql/data/recovery.conf

#. /etc/rc.d/rc.pgsqld restart



O parâmetro: trigger_file = '/tmp/trigger.pgsql.5432' é apenas um arquivo vazio que diz que é um servidor standby, isto é,
slave (read-only), daí nome trigger_file (arquivo_gatilho).

No servidor Master (ip: 10.3.128.1)

Concluindo o backup do Master para os Slaves...

usr/local/data/pgsql/bin/psql -d postgres -c "SELECT pg_stop_backup();"


Neste momento o Master estará em modo read-write (escrita e leitura) e os Slaves sicronizados podendo fazer consultas;
estarão em modo read-only (somente-leitura).

Monitoramento da Replicação:

Via Query: (Com o pgAdmin III)

--Informações sobre o servidor standby (slave)
--ultimo fragmento recebido do servidor de producao 
SELECT * 
  FROM pg_last_xlog_receive_location()
     ;
--ultimo fragmento aplicado durante a recuperacao
--valores idênticos para as duas funções indicam que não há informações pendentes a serem aplicadas 
SELECT * 
  FROM pg_last_xlog_replay_location()
     ;
--indica se o servidor Postgres está em restauração
SELECT * 
  FROM pg_is_in_recovery()
     ;


Via Shell: (pg_controldata)

O aplicativo pg_controldata exibe varias informações de controle do WAL, a ser executado no shell,
para comparação entre o Master e os Slaves.

#./pg_controldata

Via Shell: (ps –efH | grep postgres)

ps –efH | grep postgres


No servidor de produção (master) é criado um processo WALSENDER para enviar os fragmentos do streaming replication

No servidor de standby (slave) é criado um processo WALRECEIVER para receber os fragmentos do streaming replication

Via Shell: (tail –f /usr/local/pgsql/data/serverlog)

No servidores é possível identificar muitos problemas ocasionados durante a replicação apenas visualizando o serverlog do Postgres.

#tail –f /usr/local/pgsql/data/serverlog


Algumas Considerações Importantes:

Consultas em servidores Slaves podem causar conflitos com operações de restauração que ocorrem em paralelo com o Master

Exemplo:
Uma operação de VACCUM FULL ao ser replicada pode remover um registro "morto" que esteja sendo utilizada por uma operação read-only.

Ao remover o registro a consulta poder trazer resultados incorretos.

Há duas maneiras de resolver esse problema:

Forma 1:

Parar a replicação até que a consulta finalize. (configurar no postgresql.conf do Master)

max_standby_delay = -1


Aguardam finalização das transações que causam conflito no servidores Slaves.

Ideal para ambientes onde as consultas são mais importantes que a sincronização dos servidores.

Forma 2:

Matar a(s) consulta(s) no(s) servidor(es) Slaves. (configurar no postgresql.conf do Master)

max_standby_delay = 0


Mata as consultas que estão causando conflito imediatamente.

Ideal para ambientes onde a sincronização é mais importante do que as consultas no servidores Slaves.

O Stream Replication isoladamente não disponibiliza servidor para consulta, apenas sincroniza os servidores
com os fragmentos (stream) dos logs de transação (WAL-LOG).

Algumas Dicas:

Recomendo para não consumir o link de banda, isto é a replicação não competir com o uso tradicional de servidor Master,
utilizar uma placa de rede adicional 10 Gigabits Ethernet, ou superior.

Automatizar o processo de failover usando Hearbeat.

Utilizar ferramentas para balanceamento de carga de consultas.

E concluindo o PostgreSQL 9.0 não contempla a Replicação Síncrona e a Replicação em Cascata,
mas há boas pespectivas futuras de que o PostgreSQL 9.1 venha a ser lançado com esses recursos,
além de um sistema de backup baseado no Streaming Replication.

Referencia:

http://www.postgresql.org
http://www.postgresql.org.br
http://planeta.postgresql.org.br/
http://blog.softa.com.br/
http://www.dextra.com.br
http://emersonhermann.blogspot.com

4 comentários:

  1. Opa cara blz?
    Viu cara to meio confuso ae, tem umas partes que parece que é dentro de um arquivo, sera que poderia especificar aonde devo colocar alguns códigos?

    ResponderExcluir
    Respostas
    1. Olá Rafa, poderia ser mais especifico na sua dúvida ?

      Excluir
  2. otimo post, já fiz replica com o postgresql 9.1 e a sincrona é mais simples de configurar, porém consome muito da capacidade de leitura e escrita no servidor master, pois grava em dois lugares ao mesmo tempo, recomendo esse post em ambiente remoto e talvez até no mesmo site, caso seja um banco grande.

    ResponderExcluir