O PostgreSQL pode trabalhar separadamente em várias máquinas com a mesma estrutura de dados, tornando a camada de persistência da aplicação mais resiliente e preparada para algum evento inesperado que possa comprometer a continuidade do serviço.
A ideia por trás disso é melhorar o tempo de resposta do sistema distribuindo as requisições em uma rede “Round Robin” onde cada nó presente é um cluster. Nesse tipo de configuração não é importante qual das requisições serão entregues para serem processadas, pois a resposta seria sempre a mesma.
Neste blog, explicaremos como replicar um cluster PostgreSQL usando as ferramentas fornecidas na instalação do programa. A versão usada é o PostgreSQL 11.5, a atual versão estável e geralmente disponível para o sistema operacional Debian Buster. Para os exemplos deste blog, supõe-se que você já esteja familiarizado com o Linux.
Programas PostgreSQL
Dentro do diretório /usr/bin/ está o programa responsável por gerenciar o cluster.
# 1. Lists the files contained in the directory
# 2. Filters the elements that contain 'pg_' in the name
ls /usr/bin/ | grep pg_
As atividades realizadas por meio desses programas podem ser realizadas sequencialmente, ou mesmo em combinação com outros programas. A execução de um bloco dessas atividades por meio de um único comando é possível graças a um programa Linux encontrado no mesmo diretório, chamado make.
Para listar os clusters presentes, use o programa pg_lsclusters. Você também pode usar make para executá-lo. Seu trabalho depende de um arquivo chamado Makefile, que precisa estar no mesmo diretório onde o comando será executado.
# 1. The current directory is checked
pwd
# 2. Creates a directory
mkdir ~/Documents/Severalnines/
# 3. Enroute to the chosen directory
cd ~/Documents/Severalnines/
# 4. Create the file Makefile
touch Makefile
# 5. Open the file for editing
A definição de um bloco é mostrada abaixo, tendo como nome ls, e um único programa a ser executado, pg_lsclusters.
# 1. Block name
ls:
# 2. Program to be executed
pg_lsclusters
O arquivo Makefile pode conter vários blocos, e cada um pode executar quantos programas você precisar, e até mesmo receber parâmetros. É imprescindível que as linhas pertencentes a um bloco de execução estejam corretas, utilizando tabulações para recuo ao invés de espaços.
O uso de make para executar o programa pg_lsclusters é feito usando o comando make ls.
# 1. Executes pg_lsclusters
make ls
O resultado obtido em uma instalação recente do PostgreSQL traz um único cluster chamado main, alocado na porta 5432 do sistema operacional. Quando o programa pg_createcluster é utilizado, uma nova porta é alocada para o novo cluster criado, tendo o valor 5432 como ponto de partida, até que outra seja encontrada em ordem crescente.
Registro de gravação antecipada (WAL)
Este procedimento de replicação consiste em fazer um backup de um cluster em funcionamento que continua recebendo atualizações. Se isso for feito na mesma máquina, no entanto, muitos dos benefícios trazidos por essa técnica são perdidos.
Escalar um sistema horizontalmente garante maior disponibilidade do serviço, pois se ocorrer algum problema de hardware, não faria muita diferença, pois existem outras máquinas prontas para assumir a carga de trabalho.
WAL é o termo usado para representar um algoritmo complexo interno ao PostgreSQL que garante a integridade das transações que são feitas no sistema. No entanto, apenas um único cluster deve ter a responsabilidade de acessá-lo com permissão de gravação.
A arquitetura agora tem três tipos distintos de clusters:
- Um principal responsável por escrever para a WAL;
- Uma réplica pronta para assumir a postagem principal;
- Outras réplicas diversas com função de leitura WAL.
As operações de gravação são quaisquer atividades destinadas a modificar a estrutura de dados, seja inserindo novos elementos ou atualizando e excluindo registros existentes.
Configuração do cluster PostgreSQL
Cada cluster possui dois diretórios, um contendo seus arquivos de configuração e outro com os logs de transações. Eles estão localizados em /etc/postgresql/11/$(cluster) e /var/lib/postgresql/11/$(cluster), respectivamente (onde $(cluster) é o nome do cluster).
O arquivo postgresql.conf é criado imediatamente após a criação do cluster executando o programa pg_createcluster, e as propriedades podem ser modificadas para a customização de um cluster.
Editar este arquivo diretamente não é recomendado porque contém quase todas as propriedades. Seus valores foram comentados, tendo o símbolo # no início de cada linha, e várias outras linhas comentadas contendo instruções para alterar os valores das propriedades.
É possível adicionar outro arquivo contendo as alterações desejadas, basta editar uma única propriedade chamada include, substituindo o valor padrão #include =‘’ por include =‘postgresql.replication.conf’.
Antes de iniciar o cluster, você precisa da presença do arquivo postgresql.replication.conf no mesmo diretório onde você encontra o arquivo de configuração original, chamado postgresql.conf.
# 1. Block name
create:
# 2. Creates the cluster
pg_createcluster 11 $(cluster) -- --data-checksums
# 3. Copies the file to the directory
cp postgresql.replication.conf /etc/postgresql/11/$(cluster)/
# 4. A value is assigned to the property
sed -i "s|^#include = ''|include = 'postgresql.replication.conf'|g" /etc/postgresql/11/$(cluster)/postgresql.conf
O uso de --data-checksums na criação do cluster adiciona um maior nível de integridade aos dados, custando um pouco de desempenho, mas sendo muito importante para evitar corrupção dos arquivos ao transferidos de um cluster para outro.
Os procedimentos descritos acima podem ser reutilizados para outros clusters, bastando passar um valor para $(cluster) como parâmetro na execução do programa make.
# 1. Executes the block 'create' by passing a parameter
sudo make create cluster=primary
Agora que uma breve automação das tarefas foi estabelecida, o que resta a ser feito é a definição do arquivo postgresql.replication.conf de acordo com a necessidade de cada cluster.
Replicação no PostgreSQL
São possíveis duas formas de replicar um cluster, sendo uma completa, outra envolvendo todo o cluster (chamada de Replicação de Streaming) e outra parcial ou completa (chamada de Replicação Lógica).
As configurações que devem ser especificadas para um cluster se enquadram em quatro categorias principais:
- Servidor mestre
- Servidores de espera
- Servidores de envio
- Assinantes
Como vimos anteriormente, WAL é um arquivo que contém as transações que são feitas no cluster, e a replicação é a transmissão desses arquivos de um cluster para outro.
Dentro das configurações presentes no arquivo postgresql.conf, podemos ver as propriedades que definem o comportamento do cluster em relação aos arquivos WAL, como o tamanho desses arquivos.
# default values
max_wal_size = 1GB
min_wal_size = 80MB
Outra propriedade importante chamada max_wal_senders. Pertencer a um cluster com a característica Sending Servers, é a quantidade de processos responsáveis por enviar esses arquivos para outros clusters, devendo sempre ter um valor maior que o número de clusters que dependem de seu recebimento.
Arquivos WAL podem ser armazenados para transmissão para um cluster que se conecta tarde, ou que teve alguns problemas em recebê-lo, e precisa de arquivos anteriores em relação ao tempo atual, tendo como especificação a propriedade wal_keep_segments para quantos segmentos de arquivo WAL devem ser mantidos por um cluster.
Um Slot de Replicação é uma funcionalidade que permite ao cluster armazenar os arquivos WAL necessários para fornecer a outro cluster todos os registros, tendo como propriedade a opção max_replication_slots.
# default values
max_wal_senders = 10
wal_keep_segments = 0
max_replication_slots = 10
Quando a intenção é terceirizar o armazenamento desses arquivos WAL, outro método de processamento desses arquivos pode ser utilizado, chamado de Arquivo Contínuo.
Arquivamento Contínuo
Este conceito permite direcionar os arquivos WAL para um local específico, usando um programa Linux e duas variáveis representando o caminho do arquivo e seu nome, como %p e %f, respectivamente.
Esta propriedade está desabilitada por padrão, mas seu uso pode ser facilmente implementado retirando a responsabilidade de um cluster de armazenar esses arquivos importantes, e pode ser adicionada ao arquivo postgresql.replication.conf.
# 1. Creates a directory
mkdir ~/Documents/Severalnines/Archiving
# 2. Implementation on postgresql.replication.conf
archive_mode = on
archive_command = 'cp %p ~/Documents/Severalnines/Archiving/%f'
# 3. Starts the cluster
sudo systemctl start [email protected]
Após a inicialização do cluster, algumas propriedades podem precisar ser modificadas e uma reinicialização do cluster pode ser necessária. No entanto, algumas propriedades só podem ser recarregadas, sem a necessidade de uma reinicialização completa de um cluster.
Informações sobre tais assuntos podem ser obtidas através dos comentários presentes no arquivo postgresql.conf, aparecendo como # (nota:mudança requer reinício).
Se este for o caso, uma forma simples de resolver é com o programa Linux systemctl, usado anteriormente para iniciar o cluster, bastando substituir a opção de reiniciar.
Quando uma reinicialização completa não é necessária, o próprio cluster pode reatribuir suas propriedades por meio de uma consulta executada dentro dele, porém, se vários clusters estiverem sendo executados na mesma máquina, será necessário passar um parâmetro contendo o valor da porta que o cluster está alocado no sistema operacional.
# Reload without restarting
sudo -H -u postgres psql -c ‘SELECT pg_reload_conf();’ -p 5433
No exemplo acima, a propriedade archive_mode requer uma reinicialização, enquanto archive_command não. Após esta breve introdução a este assunto, vamos ver como um cluster de réplica pode fazer backup desses arquivos WAL arquivados, usando o Point In Time Recovery (PITR).
Recuperação pontual da replicação PostgreSQL
Esse nome sugestivo permite que um cluster volte ao seu estado a partir de um determinado período de tempo. Isso é feito através de uma propriedade chamada recovery_target_timeline, que espera receber um valor no formato de data, como 2019-08-22 12:05 GMT, ou a atribuição mais recente, informando a necessidade de recuperação até o último registro existente.
O programa pg_basebackup quando executado, faz uma cópia de um diretório contendo os dados de um cluster para outro local. Este programa tende a receber vários parâmetros, sendo um deles -R, que cria um arquivo chamado recovery.conf dentro do diretório copiado, que por sua vez não é o mesmo que contém os outros arquivos de configuração vistos anteriormente, como postgresql.conf .
O arquivo recovery.conf armazena os parâmetros passados na execução do programa pg_basebackup, e sua existência é essencial para a implementação da Streaming Replication, pois é dentro dele que a operação inversa ao Arquivo Contínuo pode ser realizado.
# 1. Block name
replicate:
# 2. Removes the current data directory
rm -rf /var/lib/postgresql/11/$(replica)
# 3. Connects to primary cluster as user postgres
# 4. Copies the entire data directory
# 5. Creates the file recovery.conf
pg_basebackup -U postgres -d postgresql://localhost:$(primaryPort) -D /var/lib/postgresql/11/$(replica) -P -R
# 6. Inserts the restore_command property and its value
echo "restore_command = 'cp ~/Documents/Severalnines/Archiving/%f %p'" >> /var/lib/postgresql/11/$(replica)/recovery.conf
# 7. The same is done with recovery_target_timeline
echo "recovery_target_timeline = 'latest'" >> /var/lib/postgresql/11/$(replica)/recovery.conf
Este bloco de replicação especificado acima precisa ser executado pelo usuário postgres do sistema operacional, para evitar possíveis conflitos com quem é o proprietário dos dados do cluster, postgres ou o usuário root.
O cluster de réplica ainda está de pé, alinhando-o para iniciar a replicação com sucesso, tendo o processo de cluster de réplica chamado pg_walreceiver interagindo com o cluster primário chamado pg_walsender em uma conexão TCP.
# 1. Executes the block ‘replicate’ by passing two parameters
sudo -H -u postgres make replicate replica=replica primaryPort=5433
# 2. Starts the cluster replica
sudo systemctl start [email protected]
A verificação da integridade desse modelo de replicação, chamada de Replicação de Streaming, é realizada por uma consulta executada no cluster primário.
# 1. Checks the Streaming Replication created
sudo -H -u postgres psql -x -c ‘select * from pg_stat_replication;’ -p 5433
Conclusão
Neste blog, mostramos como configurar a replicação de streaming assíncrona entre dois clusters PostgreSQL. Lembre-se, porém, que existem vulnerabilidades no código acima, por exemplo, usar o usuário postgres para fazer tal tarefa não é recomendado.
A replicação de um cluster traz diversos benefícios quando é utilizado da forma correta e tem fácil acesso às APIs que passam a interagir com os clusters.