PostgreSQL e configurações de consistência de gravação para cada conexão específica

A tradução do artigo foi preparada especialmente para os alunos do curso «Bancos de Dados». Está interessado em se desenvolver nesta área? Convidamos você para o Dia de Portas Abertas, onde explicamos em detalhes sobre o programa, as características do formato online, as competências e as perspectivas de carreira que aguardam os graduados após a formação.

PostgreSQL e configurações de consistência de gravação para cada conexão específica

PostgreSQL e configurações de consistência de gravação para cada conexão específica
Na Compose, lidamos com muitos bancos de dados, e isso nos permite conhecer melhor suas funcionalidades e limitações. À medida que aprendemos a apreciar os recursos funcionais de novos bancos de dados, às vezes começamos a pensar em como seria bom se essas funcionalidades também estivessem presentes em ferramentas mais maduras com as quais já trabalhamos há muito tempo. Um dos novos recursos que gostaríamos de ver no PostgreSQL era a consistência de gravação configurável por conexão em todo o cluster. E, como se revelou, já temos isso, e hoje queremos compartilhar com você informações sobre como você pode usá-lo.

Por que isso é relevante para mim?

A forma como o cluster deve se comportar depende do seu aplicativo. Vamos dar um exemplo, um aplicativo de pagamento de contas. Você vai precisar de consistência de 100% no cluster, então terá que habilitar commits síncronos para que seu banco de dados espere até que todas as mudanças sejam feitas. No entanto, se seu aplicativo for uma rede social em rápido crescimento, é bem provável que você prefira uma resposta rápida em vez de 100% de consistência. Para alcançar isso, você pode usar commits assíncronos em seu cluster.

Conheça, o compromisso

Você precisará fazer um compromisso entre a consistência dos dados e o desempenho. O PostgreSQL avança na direção da consistência, pois a configuração padrão nesse caso se torna previsível e sem surpresas indesejadas. Agora, vamos nos familiarizar com os compromissos.

Compromisso 1: Desempenho

Se um cluster PostgreSQL não requer consistência, ele pode operar de forma assíncrona. As gravações são feitas no líder do cluster, e suas réplicas receberão as atualizações após alguns milissegundos. Quando o cluster PostgreSQL requer consistência, ele deve operar de forma síncrona. As gravações serão feitas no líder do cluster, que enviará as atualizações para as réplicas e aguardará a confirmação de que cada uma gravou os dados antes de enviar a confirmação ao cliente que iniciou a gravação, informando que foi concluída com sucesso. A diferença prática entre esses métodos é que o método assíncrono requer duas idas pela rede, enquanto o síncrono requer quatro.

Compromisso 2: Consistência

O resultado em caso de falha do líder nesses dois abordagens também será diferente. Se o trabalho for executado de forma assíncrona, ao ocorrer um erro desse tipo, nem todas as gravações estarão confirmadas pelas réplicas. Quanto será perdido? Depende do próprio aplicativo e da eficácia da replicação. A replicação Compose impedirá que a réplica se torne o líder caso a quantidade de informações nela seja 1 MB menor do que a do líder, ou seja, potencialmente até 1 MB de gravações pode ser perdido durante a operação assíncrona.

No modo síncrono, isso não ocorre. Se o líder falhar, todas as réplicas são atualizadas, pois qualquer gravação confirmada no líder deve ser confirmada nas réplicas. Aqui está a consistência.

O comportamento síncrono faz sentido em um aplicativo de pagamento de contas, onde a consistência tem uma vantagem clara na busca por um compromisso entre consistência e desempenho. O mais importante para tal aplicativo são os dados válidos. Agora, lembre-se de uma rede social, na qual a tarefa principal é manter a atenção do usuário, respondendo às solicitações o mais rápido possível. Nesse caso, o desempenho com menos idas pela rede e menos espera pelos commits terá prioridade. No entanto, o compromisso entre desempenho e consistência não é o único que deve ser considerado.

Compromisso 3: Falhas

É muito importante entender como um cluster se comporta durante uma falha. Vamos considerar a situação em que uma ou mais réplicas falham. Quando os commits são processados de forma assíncrona, o líder continuará funcionando, ou seja, aceitará e processará entradas sem esperar pelas réplicas ausentes. Quando as réplicas retornarem ao cluster, elas se alinharão com o líder. Com a replicação síncrona, se as réplicas não responderem, o líder não terá escolha e continuará esperando a confirmação do commit até que a réplica retorne ao cluster e possa aceitar e confirmar a entrada.

Uma conexão por transação?

Cada aplicação necessita de um tipo especial de combinação entre consistência e desempenho. A menos que seja a nossa aplicação de pagamento de contas, que imaginamos totalmente consistente, ou a nossa quase efêmera aplicação de rede social. Em todos os outros casos, haverá momentos em que algumas operações devem ser síncronas e outras assíncronas. Você pode não querer que o sistema espere até que uma mensagem enviada no chat seja confirmada, mas se nesse mesmo aplicativo um pagamento estiver em andamento, então a espera será necessária.

Todas essas decisões, claro, são tomadas pelo desenvolvedor da aplicação. Decidir corretamente quando aplicar uma abordagem ou outra ajudará a extrair o máximo do cluster. É importante que o desenvolvedor possa alternar entre elas no nível do SQL para conexões e para transações.

Implementando controle na prática

Por padrão, o PostgreSQL garante consistência. Isso é controlado pela configuração do servidor synchronous_commit. Por padrão, ele está definido como ativado, mas possui outras três opções: local, remote_write ou off.

Ao definir o parâmetro como off todas as confirmações síncronas são interrompidas, mesmo no sistema local. O parâmetro em local define o modo síncrono para o sistema local, mas as entradas nas réplicas são feitas de forma assíncrona. Remote_write vai ainda mais longe: as entradas nas réplicas são feitas de forma assíncrona, mas retornam quando a réplica aceita a entrada, mas não a gravou no disco.

Considerando o conjunto de opções disponível, escolhemos o comportamento e, lembrando que ativado — são entradas síncronas, escolheremos local para commits assíncronos pela rede, mantendo os commits locais síncronos.

Agora, vamos mostrar como configurar isso em um instante, mas imagine que instalamos synchronous_commit em local para o servidor. Nós nos perguntamos se é possível alterar o parâmetro synchronous_commit em tempo real, e descobrimos que não só é possível, como existem dois métodos para isso. O primeiro é definir a sessão da sua conexão da seguinte forma:

SET SESSION synchronous_commit TO ON;  
// Suas gravações vão aqui

Todos os registros subsequentes na sessão confirmarão as operações de gravação para as réplicas antes de retornar um resultado positivo ao cliente conectado. Se, é claro, você não alterar a configuração synchronous_commit novamente. É possível omitir a parte SESSION no comando, pois ela estará no valor padrão.

O segundo método é bom quando você só quer garantir que está obtendo uma replicação síncrona para uma transação. Em muitos bancos de dados de geração 'NoSQL', o conceito de transações não existe, mas ele existe no PostgreSQL. Neste caso, você inicia uma transação e então define synchronous_commit em ativado antes de executar a gravação para a transação. COMMIT confirmará a transação, usando qualquer valor do parâmetro synchronous_commit, que foi definido naquele momento, embora seja melhor definir a variável com antecedência, para garantir que outros desenvolvedores entendam que as gravações não são assíncronas.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Suas gravações vão aqui
COMMIT;  

Todos os commits de transações agora serão confirmados como gravados nas réplicas antes mesmo da base de dados retornar uma resposta positiva ao cliente conectado.

Configuração do PostgreSQL

Antes disso, nós imaginávamos um sistema PostgreSQL com synchronous_commit, definido em local. Para que isso seja real do lado do servidor, você precisará definir dois parâmetros de configuração do servidor. Outro parâmetro synchronous_standby_names entrará em vigor quando synchronous_commit estiver em ativado. Ele define quais réplicas têm permissão para commits síncronos, e nós o configuraremos em *, o que significará ativar todas as réplicas. Esses valores geralmente são configurados em arquivo de configuração adicionando:

synchronous_commit = local  
synchronous_standby_names='*'

Definindo o parâmetro synchronous_commit como valor local, estamos criando um sistema onde os discos locais permanecem síncronos, mas os commits das réplicas de rede são, por padrão, assíncronos. Se, é claro, não decidirmos tornar esses commits síncronos, como mostrado acima.

Se você acompanhou o desenvolvimento do projeto Governor, você pode ter notado algumas mudanças recentes (1, 2), que permitiu aos usuários do Governor testar esses parâmetros e controlar sua consistência.

Mais algumas palavras…

Literalmente, uma semana atrás, eu diria que não era possível ajustar tão finamente o PostgreSQL. Foi então que Kurt, membro da equipe da plataforma Compose, insistiu que essa possibilidade existia. Ele acalmou minhas objeções e encontrou na documentação do PostgreSQL o seguinte:

PostgreSQL e configurações de consistência de gravação para cada conexão específica

Esse parâmetro pode ser alterado a qualquer momento. O comportamento de qualquer transação é determinado pela configuração em vigor no momento do commit. Portanto, pode ser útil que alguns commits de transações sejam feitos de forma síncrona, enquanto outros o sejam de forma assíncrona. Por exemplo, para fazer uma multistatement transação realizar commits de forma assíncrona, quando o valor padrão do parâmetro é oposto, defina SET LOCAL synchronous_commit TO OFF na transação.

Com essa pequena modificação no arquivo de configuração, concedemos aos usuários o controle sobre sua consistência e desempenho.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster