Thursday, November 11, 2010

Replicação no PostgreSQL

Este é o primeiro artigo (introdutório) de uma série de artigos sobre replicação no PostgreSQL. A ideia é desvendar como realizar replicação no PostgreSQL explicando cada passo a ser realizado. Os primeiros artigos conterão soluções de replicação nativas do PostgreSQL; na sequência irei abordar outras ferramentas (que não são distribuídas com o PostgreSQL) utilizadas para fazer replicação. Então, por que preciso replicar?

Um servidor de banco de dados pode estar trabalhando bem em uma solução que contém vários servidores de aplicação e milhares de clientes. No entanto, as empresas estão muito interessadas em distribuir o processamento enquanto mantêm a integração dos recursos de informação. Em um determinado momento poderá surgir a necessidade de ter um outro servidor de banco de dados que contenha todos os dados ou parte deles para fins de disponibilidade, confiabilidade, desempenho e/ou balanceamento de carga.

Vários tipos de servidores, tais como servidores web, servidores DNS e servidores de aplicação, que contém dados estáticos podem ser combinados facilmente para atender requisições balanceando a carga entre eles. Da mesma maneira, isso pode ser feito para servidores de bancos de dados. No entanto, servidores de bancos de dados geralmente não possuem dados puramente estáticos.Se permitirmos alteração no servidor de banco de dados, ainda temos que garantir a atomicidade (vide ACID) -- o que nem sempre é um problema nos outros tipos de servidores. Isto torna soluções de replicação em servidores de bancos de dados mais complexas do que em outros tipos de servidores.

As soluções de replicação disponíveis em SGBDs podem ser classificadas quanto a sincronia, escrita, fragmentação, envio e modo.
  • sincronia: os dados podem ser sincronizados "simultaneamente" ou após algum tempo;
    • síncrono: a transação é efetivada "simultaneamente" em todos os servidores que participam da replicação;
    • assíncrono: após a transação ser efetivada em um servidor, ela é propagada para os outros servidores.
  • escrita: os dados podem ser escritos em qualquer servidor, alguns servidores ou somente em um servidor. Servidor principal (também chamado de mestre) é aquele que aceita escrita. Servidor secundário (também chamado de escravo) é aquele que aceita somente leitura;
    • múltiplos mestres: os dados podem ser escritos em múltiplos servidores e serão enviados para os outros servidores que participam da replicação;
    • um mestre: somente um servidor (principal/mestre) aceita escrita de dados. Os outros servidores só recebem as alterações feitas no servidor principal.
  • fragmentação: os dados de uma relação são particionados em múltiplos servidores.
    • horizontal: cada fragmento (que está em um servidor) contém um subconjunto das tuplas da relação completa, ou seja, a união dos fragmentos resulta na relação completa;
    • vertical: cada fragmento (que está em um servidor) contém um subconjunto dos atributos da relação, ou seja, cada fragmento é uma projeção da relação completa;
  • envio: os dados podem ser enviados quando o arquivo que contém logs de transação é fechado ou quando uma transação é efetivada;
    • envio de arquivo: após o preenchimento (fechamento) de um arquivo que contém logs de transação, este é enviado a outros servidores que aplicam os logs de transação. Este tipo geralmente é utilizado em combinação com envio assíncrono;
    • envio de registro: após a efetivação de uma transação, o log (registro) da transação é enviado e aplicado nos servidores que participam da replicação;
  • modo: os servidores secundários podem aceitar ou não consultas (somente leitura). Este tipo é utilizado com escrita somente em um servidor principal;
    • warm standby: os servidores secundários (aqueles que não recebem escrita) não aceitam conexões (e consultas);
    • hot standby: os servidores secundários aceitam conexões e consultas que não modificam dados;
Uma solução de replicação pode combinar várias dessas caraterísticas para atender uma determinada necessidade. O PostgreSQL aceita nativamente quase todos as características citadas acima exceto síncrono (possivelmente teremos na versão 9.1), múltiplos mestres (sem previsão -- uma ferramenta externa como o Bucardo pode suprir esta necessidade) e fragmentação (uma ferramenta externa como o PL/Proxy pode suprir esta necessidade).
Pela complexidade de gerenciamento e perda de performance, a escrita em múltiplos servidores ao mesmo tempo não é muito comum. Cenários com múltiplos servidores mestres exigem que as aplicações "saibam" que há múltiplos servidores que aceitam escrita para evitar possíveis conflitos (mesmo dado alterado em dois servidores) ou impasses (deadlocks). As soluções de replicação mais comuns são aquelas que recebem alterações somente em um servidor (principal) e enviam as modificações realizadas no mesmo para os outros servidores (secundários). Caso o servidor principal falhe, podemos promover um servidor secundário a servidor principal.

Podemos caracterizar as soluções nativas do PostgreSQL quanto a sincronia (assíncrono), escrita (um mestre), envio (arquivo, registro) e modo (warm standby, hot standby). Assim, há quatro possíveis cenários para replicação nativo no PostgreSQL:
  • warm standby e envio de arquivo: os servidores secundários não aceitam conexões e se mantêm atualizados de modo assíncrono através dos arquivos de log de transação enviados pelo servidor principal após serem preenchidos ou depois de determinado tempo. Esta solução está disponível desde a versão 8.0;
  • warm standby envio de registro: os servidores secundários não aceitam conexões e se mantêm atualizados de modo assíncrono através dos logs de transação que são enviados pelo servidor principal e aplicados nos servidores secundários. Esta solução está disponível desde a versão 9.0;
  • hot standby e envio de arquivo: os servidores secundários aceitam consultas somente leitura e se mantêm atualizados de modo assíncrono através dos arquivos de log de transação enviados pelo servidor principal após serem preenchidos ou depois de determinado tempo. Esta solução está disponível desde a versão 9.0;
  • hot standby e envio de registro: os servidores secundários aceitam consultas somente leitura e se mantêm atualizados de modo assíncrono através dos logs de transação enviados pelo servidor principal e aplicados nos servidores secundários. Esta solução está disponível desde a versão 9.0.
Apresentaremos a implementação dos quatros tipos de replicação descritos acima utilizando o seguinte cenário.




Os pré-requisitos são:
  • 2 servidores: utilizaremos dois servidores. Um servidor principal (aceita leitura e modificação de dados) e outro servidor secundário (pode aceitar ou não consultas somente leitura). Estes servidores devem ser preferencialmente (quase) idênticos pois a replicação é binária, sendo incompatível em arquiteturas e/ou sistemas operacionais distintos. A arquitetura deve ser a mesma; o sistema operacional pode ser diferente mas para evitar problemas de incompatibilidade de hardware, bugs ou perda de performance, aconselhamos que utilize a mesma versão;
  • PostgreSQL: a mesma versão deve ser utilizada. A mesma versão corretiva não é necessária (podemos utilizar 9.0.0 e 9.0.1) mas não é aconselhável ter servidores secundários com versão menor do que servidores principais. Se possível, utilize exatamente a mesma versão em todos os servidores;
  • Acesso: você deve ter acesso remoto aos 2 servidores. Talvez seja necessário o acesso super-usuário (root) no servidor secundário para criar o diretório de dados e definir permissões. É necessário acesso super-usuário no PostgreSQL do servidor principal;
  • Rede: deve ser possível acessar a porta (geralmente 5432) do servidor principal a partir do servidor secundário. Certifique que o firewall não esteja bloqueando este acesso. Além disso, no momento da cópia física dos arquivos deve ser possível enviá-los (por ssh, ftp, dentre outros) do servidor principal para o servidor secundário ou vice-versa;
  • Interface de Rede: os servidores principal e secundário possuem respectivamente os endereços de rede 10.1.1.1 e 10.1.1.2;
  • Diretório de Dados: os diretórios de dados do servidor principal e secundário estão respectivamente em /bd/primario e /bd/secundario. O arquivamento de arquivos de log de transação feito no servidor secundário está em /bd/arquivamento;
  • Usuário: o usuário do sistema operacional que iniciará o PostgreSQL em ambos servidores será o postgres.