Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Em sua palestra, Andrey Borodin contará como eles levaram em consideração a experiência de dimensionamento do PgBouncer ao projetar um pooler de conexão Odyssey, como eles o lançaram na produção. Além disso, discutiremos quais funções do pooler gostaríamos de ver em novas versões: é importante para nós não apenas atender às nossas necessidades, mas também desenvolver a comunidade de usuários Odisséia.

Vídeo:

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Olá a todos! Meu nome é Andrew.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

No Yandex, estou desenvolvendo bancos de dados de código aberto. E hoje temos um tópico sobre conexões do pooler de conexões.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Se você sabe como chamar o pooler de conexões em russo, diga-me. Eu realmente quero encontrar um bom termo técnico que deva ser estabelecido na literatura técnica.

O assunto é bem complicado, pois em muitos bancos de dados o pooler de conexões já vem embutido e você nem precisa saber disso. Algumas configurações, é claro, estão por toda parte, mas no Postgres isso não funciona. E em paralelo (no HighLoad++ 2019) há um relatório de Nikolai Samokhvalov sobre a configuração de consultas no Postgres. E eu entendo que vieram aqui pessoas que já configuraram perfeitamente as solicitações, e são pessoas que se deparam com problemas de sistema mais raros relacionados à rede, utilização de recursos. E em alguns lugares pode ser bastante difícil no sentido de que os problemas não são óbvios.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Yandex tem Postgres. Muitos serviços Yandex residem no Yandex.Cloud. E temos vários petabytes de dados que geram pelo menos um milhão de requisições por segundo no Postgres.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E fornecemos um cluster bastante típico para todos os serviços - este é o principal nó primário do nó, as duas réplicas usuais (síncrona e assíncrona), backup, dimensionamento de solicitações de leitura na réplica.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Cada nó do cluster é Postgres, no qual, além do Postgres e dos sistemas de monitoramento, também está instalado um pooler de conexões. O pooler de conexões é usado para cercas e para seu propósito principal.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Qual é o principal objetivo de um pooler de conexão?

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

O Postgres adota um modelo de processo para trabalhar com um banco de dados. Isso significa que uma conexão é um processo, um back-end do Postgres. E há muitos caches diferentes neste back-end, que são muito caros para serem diferentes para conexões diferentes.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Além disso, existe um array no código Postgres chamado procArray. Ele contém dados básicos sobre conexões de rede. E quase todos os algoritmos de processamento procArray têm complexidade linear, eles percorrem toda a matriz de conexões de rede. É um ciclo bastante rápido, mas com mais conexões de rede de entrada, as coisas ficam um pouco mais caras. E quando as coisas ficam um pouco mais caras, você acaba pagando um preço muito alto por um grande número de conexões de rede.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Existem 3 abordagens possíveis:

  • Do lado da aplicação.
  • Do lado do banco de dados.
  • E entre, ou seja, todas as combinações possíveis.

Infelizmente, o pooler integrado está atualmente em desenvolvimento. Amigos do PostgreSQL Professional fazem isso principalmente. Quando vai aparecer é difícil prever. E de facto, temos duas soluções para a escolha de um arquitecto. Estes são o pool do lado do aplicativo e o pool de proxy.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

O pool do lado do aplicativo é a maneira mais fácil. E quase todos os drivers de cliente fornecem uma maneira: representar milhões de suas conexões no código como algumas dezenas de conexões com o banco de dados.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Há um problema com o fato de que em um determinado ponto você deseja escalar o back-end, deseja implantá-lo em muitas máquinas virtuais.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Aí você ainda percebe que tem mais várias zonas de disponibilidade, vários datacenters. E a abordagem de pooling do lado do cliente leva a grandes números. Os grandes são cerca de 10 conexões. Esta é uma vantagem que pode funcionar bem.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Se falamos de poolers de proxy, existem dois poolers que podem fazer muitas coisas. Eles não são apenas poolers. Eles são poolers + funcionalidade mais legal. Esse pgpool и Proxy Crocante.

Mas, infelizmente, nem todo mundo precisa dessa funcionalidade adicional. E isso leva ao fato de que os poolers oferecem suporte apenas ao pool de sessões, ou seja, um cliente de entrada, um cliente de saída para o banco de dados.

Isso não é muito adequado para nossas tarefas, então usamos o PgBouncer, que implementa o pool de transações, ou seja, as conexões do servidor são mapeadas para as conexões do cliente apenas durante a transação.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E em nossa carga - é verdade. Mas há vários problemas.Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Os problemas começam quando você deseja diagnosticar uma sessão, porque todas as conexões de entrada são locais. Todos vieram com loopback e de alguma forma fica difícil rastrear a sessão.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Claro que você pode usar application_name_add_host. Esta é a maneira do lado do Bouncer de adicionar um endereço IP ao application_name. Mas application_name é definido por uma conexão adicional.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Neste gráfico, onde a linha amarela são as solicitações reais e a linha azul são as solicitações que chegam ao banco de dados. E essa diferença é justamente a configuração do application_name, que só é necessário para o rastreamento, mas não é nada gratuito.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Além disso, o Bouncer não pode limitar um pool, ou seja, o número de conexões de banco de dados por usuário, por banco de dados.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

A que isso leva? Você tem um serviço carregado escrito em C ++ e em algum lugar próximo um pequeno serviço em um nó que não faz nada de errado com a base, mas seu driver enlouquece. Abre 20 conexões e todo o resto vai esperar. Até o seu código está correto.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Claro, escrevemos um pequeno patch para o Bouncer que adicionou essa configuração, ou seja, limitando os clientes ao pool.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Seria possível fazer isso no lado do Postgres, ou seja, limitar as funções no banco de dados ao número de conexões.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Mas então você perde a capacidade de entender por que não tem conexões com o servidor. O PgBouncer não lança um erro de conexão, ele sempre retorna a mesma informação. E você não consegue entender: talvez sua senha tenha mudado, talvez o banco de dados tenha caído, talvez algo esteja errado. Mas não há diagnóstico. Se a sessão não puder ser estabelecida, você não saberá por que isso não pode ser feito.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Em determinado momento, você olha os gráficos do aplicativo e vê que o aplicativo não está funcionando.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Olhe para o topo e veja que Bouncer é single-threaded. Este é um ponto de viragem na vida do serviço. Você entende que estava se preparando para dimensionar o banco de dados em um ano e meio e precisa dimensionar o pooler.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Chegamos à conclusão de que precisamos de mais PgBouncers.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

https://lwn.net/Articles/542629/

Bouncer foi ligeiramente corrigido.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E eles fizeram isso para que vários Bouncers possam ser levantados com a reutilização da porta TCP. E o sistema operacional já transfere automaticamente as conexões TCP de entrada entre eles por round-robin'om.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Isso é transparente para os clientes, ou seja, parece que você tem um Bouncer, mas há fragmentação de conexões ociosas entre os Bouncers em execução.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E em algum momento, você pode perceber que esses 3 Bouncers comem 100% de seu núcleo. Você precisa de alguns Bouncers. Por que?

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Porque você tem TLS. Você tem uma conexão criptografada. E se você comparar o Postgres com e sem TLS, descobrirá que o número de conexões estabelecidas cai quase duas ordens de magnitude com a criptografia habilitada, porque o handshake TLS consome recursos da CPU.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E no topo, você pode ver algumas funções criptográficas que são executadas durante uma onda de conexões recebidas. Como nosso principal pode alternar entre as zonas de disponibilidade, uma onda de conexões de entrada é uma situação bastante típica. Ou seja, por algum motivo, o primário antigo não estava disponível, toda a carga foi enviada para outro data center. Todos virão cumprimentar o TLS ao mesmo tempo.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E um grande número de aperto de mão TLS pode não cumprimentar Bouncer, mas apertar sua garganta. Uma onda de conexões de entrada pode ficar sem amortecimento devido ao tempo limite. Se você tentar novamente a base sem uma retirada exponencial, eles não voltarão repetidamente em uma onda coerente.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Aqui está um exemplo de 16 PgBouncers que carregam 16 núcleos a 100%.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Chegamos ao PgBouncer em cascata. Esta é a melhor configuração que podemos alcançar em nossa carga Bouncer. Nossos Bouncers externos servem para handshake TCP, e Bouncers internos servem para pooling real, para não fragmentar muito as conexões externas.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Nesta configuração, uma reinicialização suave é possível. Você pode reiniciar todos esses 18 Bouncers, um por um. Mas manter essa configuração é bastante difícil. Os administradores de sistema, DevOps e as pessoas realmente responsáveis ​​por este servidor não ficarão muito felizes com este esquema.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Parece que todas as nossas melhorias podem ser promovidas em código aberto, mas o Bouncer não suporta muito bem. Por exemplo, a capacidade de executar vários PgBouncers na mesma porta foi confirmada há um mês. Uma solicitação pull com esse recurso foi há alguns anos.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

https://www.postgresql.org/docs/current/libpq-cancel.html

https://github.com/pgbouncer/pgbouncer/pull/79

Ou mais um exemplo. No Postgres, você pode cancelar uma solicitação em execução enviando o segredo para outra conexão sem a autenticação extra. Mas alguns clientes simplesmente enviam uma redefinição de TCP, ou seja, eles interrompem a conexão de rede. O que Bouncer fará com isso? Ele não fará nada. Ele continuará a executar a solicitação. Se você recebeu um grande número de conexões que estabeleceram a base com pequenas solicitações, simplesmente desconectar a conexão do Bouncer não será suficiente, você também precisará concluir as solicitações que estão sendo executadas no banco de dados.

Isso foi corrigido e o problema ainda não foi mesclado no upstream do Bouncer.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E assim chegamos à conclusão de que precisamos do nosso próprio pooler de conexões, que será desenvolvido, corrigido, no qual será possível corrigir problemas rapidamente e que, claro, deve ser multithread.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Definimos multithreading como a tarefa principal. Precisamos ser capazes de lidar bem com a onda de conexões TLS recebidas.

Para fazer isso, tivemos que desenvolver uma biblioteca separada chamada Machinarium, projetada para descrever os estados da máquina de uma conexão de rede como um código serial. Se você observar o código-fonte da libpq, verá chamadas bastante complexas que podem retornar um resultado para você e dizer: "Me ligue um pouco mais tarde. No momento, tenho IO por enquanto, mas quando o IO passa, tenho uma carga no processador. E este é um esquema de vários níveis. A interação de rede geralmente é descrita por uma máquina de estado. Muitas regras como "Se eu recebi anteriormente um cabeçalho de pacote de tamanho N, agora estou esperando por N bytes", "Se eu enviei um pacote SYNC, agora estou esperando por um pacote com metadados de resultado." Acontece um código contra-intuitivo bastante difícil, como se o labirinto fosse convertido em uma varredura de linha. Fizemos isso para que, em vez de uma máquina de estado, o programador descreva o principal caminho de interação na forma de um código imperativo comum. Apenas neste código imperativo, você precisa inserir locais onde a sequência de execução precisa ser interrompida aguardando dados da rede, passando o contexto de execução para outra co-rotina (thread verde). Essa abordagem é semelhante ao fato de escrevermos o caminho mais esperado no labirinto em uma linha e, em seguida, adicionarmos ramificações a ele.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Como resultado, temos um thread que faz um TCP aceitar e o round-robin passa uma conexão TPC para muitos trabalhadores.

Nesse caso, cada conexão de cliente sempre é executada em um processador. E isso permite que você o torne compatível com o cache.

Além disso, melhoramos ligeiramente a coleta de pequenos pacotes em um grande pacote para descarregar a pilha TCP do sistema.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Além disso, aprimoramos o pooling transacional no sentido de que o Odyssey, quando configurado, pode enviar CANCEL e ROLLBACK em caso de falha na conexão de rede, ou seja, se ninguém estiver aguardando a solicitação, o Odyssey avisará o banco de dados para não tentar atender o pedido que pode desperdiçar recursos preciosos.

E sempre que possível, mantemos conexões com o mesmo cliente. Isso evita ter que reinstalar application_name_add_host. Se possível, não temos uma redefinição adicional dos parâmetros necessários para o diagnóstico.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Trabalhamos no interesse do Yandex.Cloud. E se você estiver usando PostgreSQL gerenciado e tiver um pooler de conexão instalado, poderá criar replicação lógica externa, ou seja, deixe-nos se quiser, usando replicação lógica. Bouncer fora do fluxo de replicação lógica não vai dar.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Este é um exemplo de configuração de replicação lógica.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Além disso, temos suporte para replicação física externa. Na nuvem, é claro, isso é impossível, porque o cluster fornecerá muitas informações sobre si mesmo. Mas em suas instalações, se você precisar de replicação física via pooler de conexão no Odyssey, é possível.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Odyssey tem monitoramento totalmente compatível com PgBouncer. Temos o mesmo console que executa quase todos os mesmos comandos. Se algo estiver faltando, envie um pull request, ou pelo menos um problema no GitHub, completaremos os comandos necessários. Mas já temos a funcionalidade principal do console PgBouncer.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E, claro, temos o encaminhamento de erros. Retornaremos o erro informado pela base. Você obterá informações porque você não está na base, não apenas que você não está nela.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Este recurso está desativado caso você precise de 100% de compatibilidade com o PgBouncer. Podemos nos comportar como Bouncer, apenas no caso.

Desenvolvimento

Algumas palavras sobre o código-fonte do Odyssey.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

https://github.com/yandex/odyssey/pull/66

Por exemplo, existem comandos "Pausar / Continuar". Eles geralmente são usados ​​para atualizar o banco de dados. Se precisar atualizar o Postgres, você pode pausá-lo no pooler de conexão, fazer um pg_upgrade e continuar. E do lado do cliente, parecerá que o banco de dados estava apenas diminuindo a velocidade. Essa funcionalidade foi trazida a nós por pessoas da comunidade. Ela ainda não morreu, mas logo tudo estará. (já morto)

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

https://github.com/yandex/odyssey/pull/73 - já morto

Além disso, um dos novos recursos do PgBouncer é o suporte à autenticação SCRAM, que também nos foi trazido por uma pessoa que não trabalha no Yandex.Cloud. Ambos são funcionalidades complexas e importantes.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Portanto, gostaria de dizer do que é feito o Odyssey, caso você também queira escrever algum código agora.

Você tem a base original do Odyssey, que conta com duas bibliotecas principais. A biblioteca Kiwi é uma implementação do protocolo de mensagens Postgres. Ou seja, o proto 3 nativo do Postgres são mensagens padrão que frontends e backends podem trocar. Eles são implementados na biblioteca Kiwi.

A biblioteca Machinarium é uma biblioteca de implementação de thread. Um pequeno fragmento deste Machinarium é escrito em assembler. Mas não se preocupe, são apenas 15 linhas.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Arquitetura da Odisséia. Há uma máquina principal executando corrotinas. Esta máquina implementa a aceitação de conexões TCP de entrada e a distribuição entre os trabalhadores.

Dentro de um trabalhador, um manipulador para vários clientes pode funcionar. E também no thread principal, o console e o processamento de tarefas crone para remover conexões que não são mais necessárias no pool estão girando.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

O Odyssey é testado usando o conjunto de testes padrão do Postgres. Acabamos de executar a verificação de instalação por meio do Bouncer e por meio do Odyssey, obtemos um div nulo. Existem vários testes relacionados à formatação de datas que falham exatamente da mesma forma no Bouncer e no Odyssey.

Além disso, existem muitos drivers que possuem seus próprios testes. E usamos seus testes para testar o Odyssey.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Além disso, devido à nossa configuração em cascata, temos que testar vários pacotes: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey para ter certeza de que, se o Odyssey estiver em alguma das partes da cascata, também funcionará conforme o esperado .

Ancinho

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Usamos o Odyssey na produção. E não seria justo se eu dissesse que tudo simplesmente funciona. Não, ou seja, sim, mas nem sempre. Por exemplo, na produção, tudo funcionou, então nossos amigos do PostgreSQL Professional vieram e disseram que tínhamos um vazamento de memória. Eles realmente eram, nós os consertamos. Mas era simples.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Em seguida, descobrimos que o pooler de conexões tem conexões TLS de entrada e conexões TLS de saída. E as conexões precisam de certificados de cliente e certificados de servidor.

Os certificados do servidor Bouncer e Odyssey são relidos pelo pcache, mas os certificados do cliente não precisam ser relidos do pcache, porque nosso Odyssey escalável eventualmente depende do desempenho do sistema de leitura desse certificado. Isso foi uma surpresa para nós, porque ele não descansou imediatamente. A princípio, ele escalava linearmente e, após 20 conexões simultâneas recebidas, esse problema se manifestou.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Pluggable Authentication Method é a capacidade de autenticar com ferramentas embutidas do lunux. No PgBouncer, ele é implementado de forma que haja um thread separado esperando por uma resposta do PAM e haja um thread principal do PgBouncer que atenda à conexão atual e possa solicitar que eles vivam no thread PAM.

Não implementamos isso por um simples motivo. Temos muitos fluxos. Por que precisamos disso?

Como resultado, isso pode criar problemas porque, se você tiver autenticação PAM e autenticação não PAM, uma grande onda de autenticação PAM poderá atrasar significativamente a autenticação não PAM. É uma daquelas coisas que não consertamos. Mas se você quiser consertar, você pode fazer isso.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Outro rake foi com o fato de termos um thread que aceita todas as conexões de entrada. Em seguida, eles são transferidos para o pool de trabalhadores, onde ocorrerá o handshake TLS.

Como resultado, se você tiver uma onda coerente de 20 conexões de rede, todas serão aceitas. E no lado do cliente, o libpq começará a relatar tempos limite. Por padrão, é como 000 segundos lá.

Se eles não puderem entrar na base ao mesmo tempo, eles não poderão entrar na base, porque tudo isso pode ser coberto por uma nova tentativa não exponencial.

Acabamos copiando o esquema PgBouncer aqui para termos um throttling do número de conexões TCP que aceitamos.

Se vemos que estamos aceitando conexões, mas elas não têm tempo para o handshake no final, as colocamos em uma fila para que não consumam recursos da CPU. Isso leva ao fato de que um handshake simultâneo pode não ser executado para todas as conexões que chegaram. Mas pelo menos alguém entrará no banco de dados, mesmo que a carga seja forte o suficiente.

Roadmap

O que você gostaria de ver no futuro em Odyssey? O que estamos prontos para desenvolver e o que esperamos da comunidade?

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Para agosto de 2019.

Era assim que o roteiro da Odyssey parecia em agosto:

  • Queríamos autenticação SCRAM e PAM.
  • Queríamos encaminhar as solicitações de leitura para o modo de espera.
  • Eu gostaria de reiniciar online.
  • E a capacidade de pausar no servidor.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Metade desse roteiro é feito, e não por nós. E isso é bom. Então, vamos discutir o que resta e adicionar mais.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Em relação ao encaminhamento de consultas somente leitura para o modo de espera? Temos réplicas que, sem atender a pedidos, vão simplesmente esquentar o ar. Precisamos deles para fornecer failover e switchover. Em caso de problemas em um dos datacenters, gostaria de ocupá-los com algum trabalho útil. Porque não podemos configurar os mesmos processadores centrais, a mesma memória de maneira diferente, porque a replicação não funcionará de outra forma.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Em princípio, no Postgres, a partir de 10, é possível especificar session_attrs ao conectar. Você pode listar todos os hosts do banco de dados na conexão e dizer por que está acessando o banco de dados: somente gravação ou leitura. E o próprio driver escolherá o primeiro host da lista de que mais gosta, que atenda aos requisitos de session_attrs.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Mas o problema com essa abordagem é que ela não controla o atraso da replicação. Você pode ter algum tipo de réplica que está atrasada por um tempo inaceitável para o seu serviço. Para fazer a execução completa de solicitações de leitura em uma réplica, de fato, precisamos suportar no Odyssey a capacidade de não funcionar quando é impossível ler.

A Odyssey precisa ir ao banco de dados de tempos em tempos e solicitar a distância de replicação do primário. E caso tenha atingido o limite, não deixe novas requisições entrarem no banco de dados, diga ao cliente que precisa reiniciar as conexões e, possivelmente, selecione outro host para executar as requisições. Isso permitirá que o banco de dados restaure rapidamente o atraso da replicação e retorne novamente para responder com uma consulta.

É difícil nomear as datas de implementação, porque é de código aberto. Mas, espero, não 2,5 anos como os colegas da PgBouncer. Este é o recurso que eu gostaria de ver no Odyssey.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Na comunidade, as pessoas perguntaram sobre o apoio à declaração preparada. Agora você pode criar uma declaração preparada de duas maneiras. Primeiro, você pode executar um comando SQL, ou seja, "preparado". Para entender esse comando SQL, precisamos aprender a entender o SQL no lado do Bouncer. Isso seria um exagero porque é um exagero, pois precisamos de todo o analisador. Não podemos analisar cada comando SQL.

Mas há uma instrução preparada no nível do protocolo de mensagem em proto3. E este é o local onde a informação de que a declaração preparada está sendo criada vem de forma estruturada. E poderíamos apoiar o entendimento de que em alguma conexão do servidor o cliente pediu para criar declarações preparadas. E mesmo que a transação seja fechada, ainda precisamos manter o servidor e o cliente conectados.

Mas aqui surge uma discrepância no diálogo, porque alguém diz que você precisa entender quais declarações preparadas o cliente criou e compartilhar a conexão do servidor entre todos os clientes que criaram essa conexão do servidor, ou seja, quem criou essa declaração preparada.

Andres Freund disse que se um cliente viesse até você que já havia criado uma declaração preparada em outra conexão de servidor, crie-a para ele. Mas parece um pouco errado executar consultas no banco de dados em vez do cliente, mas do ponto de vista de um desenvolvedor que escreve um protocolo para interagir com o banco de dados, seria conveniente se ele simplesmente recebesse uma conexão de rede que tem tal pedido preparado.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

E mais um recurso que precisamos implementar. Agora temos monitoramento compatível com PgBouncer. Podemos retornar o tempo médio de execução da consulta. Mas o tempo médio é a temperatura média no hospital: alguém está com frio, alguém está quente - em média, todos estão saudáveis. Não é verdade.

Precisamos implementar suporte para percentis, o que indicaria que há solicitações lentas que consomem recursos e tornariam o monitoramento mais aceitável.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

O mais importante é que eu quero a versão 1.0 (a versão 1.1 já foi lançada). O fato é que agora o Odyssey está na versão 1.0rc, ou seja, candidato a lançamento. E todo o rake que listei foi corrigido exatamente com a mesma versão, exceto pelo vazamento de memória.

O que a versão 1.0 significará para nós? Estamos lançando o Odyssey em nossas bases. Já está rodando em nossos bancos de dados, mas quando chega ao ponto de 1 de requisições por segundo, então podemos dizer que esta é uma versão de lançamento e esta é uma versão que pode ser chamada de 000.

Várias pessoas na comunidade pediram mais pausa e SCRAM na versão 1.0. Mas isso significa que precisaremos lançar a próxima versão para produção, porque nem o SCRAM nem a pausa foram mesclados ainda. Mas, provavelmente, esse problema será resolvido rapidamente.

Roteiro Odyssey: o que mais queremos de um pooler de conexões. Andrei Borodin (2019)

Aguardo seu pull request. E também gostaria de saber quais problemas você tem com o Bouncer. Vamos discuti-los. Talvez possamos implementar algumas funções que você precisa.

Isso conclui minha parte, eu gostaria de ouvir de você. Obrigado!

perguntas

Se eu colocar meu próprio application_name, ele será lançado corretamente, inclusive no pool de transações no Odyssey?

Odyssey ou Bouncer?

Na Odisseia. O Bouncer é arremessado.

Faremos um conjunto.

E se minha conexão real pular sobre outras conexões, ela será transmitida?

Faremos um conjunto de todos os parâmetros listados. Não sei dizer se application_name está nesta lista. Parece que ele o viu lá. Vamos definir todos os mesmos parâmetros. Com uma solicitação, o conjunto fará tudo o que foi instalado pelo cliente durante a inicialização.

Obrigado Andrey pelo relato! Boa reportagem! Fico feliz que a Odyssey esteja se desenvolvendo cada vez mais rápido a cada minuto. Eu gostaria de continuar o mesmo. Já solicitamos que você tenha uma conexão de várias fontes de dados para que o Odyssey possa se conectar a diferentes bancos de dados ao mesmo tempo, ou seja, o mestre escravo e, em seguida, conectar-se automaticamente ao novo mestre após um failover.

Sim, parece que me lembro dessa discussão. Agora existem vários armazenamentos. Mas não há alternância entre eles. De nossa parte, devemos consultar o servidor se ele ainda está ativo e entender que ocorreu um failover, que chamará pg_recovery. Eu tenho uma maneira padrão de entender que não viemos ao mestre. E devemos entender de alguma forma dos erros ou como? Ou seja, a ideia é interessante, está sendo discutida. Escreva mais comentários. Se você tem mãos de trabalho que conhecem C, isso geralmente é maravilhoso.

A questão do escalonamento entre réplicas também é de nosso interesse, porque queremos tornar a adoção de clusters replicados o mais simples possível para os desenvolvedores de aplicativos. Mas aqui eu gostaria de mais comentários, ou seja, como fazer, como fazer bem feito.

A questão também é sobre réplicas. Acontece que você tem um mestre e várias réplicas. E é claro que eles vão para a réplica com menos frequência do que para o mestre para conexões, porque podem ter uma diferença. Você disse que a diferença de dados pode ser tanta que seu negócio não vai satisfazer e você não vai lá até que seja replicado. Ao mesmo tempo, se você não for lá por muito tempo e depois começar a ir, os dados de que você precisa não estarão disponíveis imediatamente. Ou seja, se formos constantemente para o mestre, o cache é aquecido lá e o cache fica um pouco atrasado na réplica.

Sim, é verdade. Não haverá blocos de dados no pcache que você deseja, no cache real não haverá informações sobre as tabelas que você deseja, não haverá consultas analisadas nos planos, nada.

E quando você tem algum tipo de cluster e adiciona uma nova réplica lá, enquanto ele inicia, tudo está ruim nele, ou seja, ele aumenta seu cache.

Eu tive a ideia. A abordagem correta seria executar primeiro uma pequena porcentagem de consultas na réplica, o que aqueceria o cache. Grosso modo, temos a condição de não estarmos mais de 10 segundos atrás do mestre. E essa condição não deve ser incluída em uma onda, mas suavemente para alguns clientes.

Sim, aumentar o peso.

Essa é uma boa ideia. Mas primeiro você precisa implementar esse desligamento. Primeiro precisamos desligar e depois pensaremos em como ligar. Este é um ótimo recurso para ativar sem problemas.

nginx tem essa opção slowly start no cluster para o servidor. E ele aumenta gradualmente a carga.

Sim, ótima ideia, vamos tentar quando chegarmos a isso.

Fonte: habr.com

Adicionar um comentário