Estamos com problemas para manipular o tráfego durante o horário de pico para nosso servidor de banco de dados. Estamos tentando melhorar o hardware (veja esta pergunta sobre esse lado ), mas também queremos trabalhar na configuração de pool e no ajuste do servidor.
A aplicação em que estamos trabalhando é um jogo multiplayer baseado em turnos para smartphones, onde o back-end consiste em Rails com unicórnio e PostgreSQL 9.1 como banco de dados. Atualmente, temos 600.000 usuários registrados e, como o estado do jogo é armazenado no banco de dados, vários milhares de gravações são feitas a cada dois segundos. Analisamos os arquivos de log do PostgreSQL usando o PgBadger e, durante as horas críticas, recebemos muitas
FATAL: remaining connection slots are reserved for non-replication superuser connections
A solução ingênua para combater esse problema seria aumentar o max_connections (que atualmente é 100) no postgresql.conf . Eu li http://wiki.postgresql.org/wiki/Number_Of_Database_Connections que indica que isso pode não ser a coisa certa a se fazer. No artigo mencionado, refere-se a encontrar o ponto ideal entre max_connections e tamanho da piscina .
O que pode ser feito para encontrar esse ponto ideal? Existem boas ferramentas para medir o desempenho de E / S para diferentes valores de max_connections e tamanho do pool ?
Nossa configuração atual é de 4 servidores de jogos, cada um com 16 trabalhadores unicórnios e um tamanho de pool de 5.
Aqui estão as configurações do postgres não padrão que estamos usando:
version | PostgreSQL 9.1.5 on x86_64-unknown-linux-gnu,compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
checkpoint_completion_target | 0.9
checkpoint_segments | 60
checkpoint_timeout | 6min
client_encoding | UTF8
effective_cache_size | 2GB
lc_collate | en_US.UTF-8
lc_ctype | en_US.UTF-8
log_destination | csvlog
log_directory | pg_log
log_filename | postgresql-%Y-%m-%d_%H%M%S.log
log_line_prefix | %t
log_min_duration_statement | 200ms
log_rotation_age | 1d
log_rotation_size | 10MB
logging_collector | on
max_connections | 100
max_stack_depth | 2MB
server_encoding | UTF8
shared_buffers | 1GB
ssl | on
TimeZone | localtime
wal_buffers | 16MB
work_mem | 8MB
fonte
synchronous_commit = off
ou acommit_delay
?INSERT
S simples ? Como é o seu esquema - ele é particionado? Qual é oexplain analyze
de algumas consultas de amostra? Qual a frequência dos seus postos de controle e quanto tempo eles demoram? (consulte as opções de log do ponto de verificação). E sério, qual é a sua versão do PostgreSQL ? (Update: Parece que você listar seu hardware aqui: dba.stackexchange.com/questions/28061/... )synchronous_commit = off
Respostas:
A resposta curta aqui é "tentativa e erro guiados por métricas de monitoramento e desempenho".
Existem algumas regras gerais que devem ajudá-lo a encontrar a área vaga em que você deve começar, mas elas são muito gerais. As diretrizes gerais "número de CPUs e número de discos independentes" são frequentemente citadas, mas é apenas um ponto de partida incrivelmente grosseiro.
O que você realmente precisa fazer é obter métricas robustas de desempenho para o seu aplicativo. Comece a gravar estatísticas.
Não há muito em termos de ferramentas integradas para isso. Existem coisas como o
check_postgres
script nagios , o registro do contador de desempenho do sistema Cacti, o coletor de estatísticas do PostgreSQL, etc ... mas não há muito que ajude tudo. Infelizmente, você terá que fazer isso sozinho. Para o lado do PostgreSQL, consulte o monitoramento no manual do PostgreSQL. Existem algumas opções de terceiros, como o Postgres Enterprise Monitor do EnterpriseDB .Para as métricas em nível de aplicativo mencionadas aqui, você deseja gravá-las em estruturas de dados compartilhadas ou em um banco de dados externo não durável como o Redis e agregá-las à medida que você as grava ou antes de gravá-las no banco de dados PostgreSQL. Tentar registrar diretamente na página distorcerá suas medidas com a sobrecarga criada pelo registro das medidas e piorará o problema.
A opção mais simples é provavelmente um singleton em cada servidor de aplicativos que você usa para registrar estatísticas do aplicativo. Você provavelmente deseja manter uma atualização constante de mín, máx, n, total e média; Dessa forma, você não precisa armazenar cada ponto de estatística, apenas os agregados. Esse singleton pode gravar suas estatísticas agregadas na página a cada x minutos, uma taxa suficientemente baixa para que o impacto no desempenho seja mínimo.
Começar com:
Qual é a latência da solicitação? Em outras palavras, quanto tempo o aplicativo leva para obter uma solicitação do cliente até responder ao cliente. Registre isso agregado por um período de tempo, e não como registros individuais. Agrupe por tipo de solicitação; digamos, por página.
Qual é o atraso de acesso ao banco de dados para cada consulta ou tipo de consulta que o aplicativo executa? Quanto tempo leva para solicitar informações ao banco de dados / armazenar informações até que esteja pronto e possa passar para a próxima tarefa? Novamente, agregue essas estatísticas no aplicativo e grave apenas as informações agregadas no banco de dados.
Como é o seu rendimento? Em um determinado x minuto, quantas consultas de cada classe principal que seu aplicativo executa são atendidas pelo banco de dados?
Para o mesmo intervalo de tempo de x minutos, quantas solicitações de clientes existiam?
Amostrando a cada poucos segundos e agregando nas mesmas janelas de x minutos no banco de dados, quantas conexões de banco de dados havia? Quantos deles estavam ociosos? Quantos estavam ativos? Em inserções? Atualizações? Selecione% s? exclui? Quantas transações houve nesse período? Consulte a documentação do coletor de estatísticas
Mais uma vez, amostrando e agregando no mesmo intervalo de tempo, como eram as métricas de desempenho do sistema host? Quantas leem e quantas E / S de disco de gravação / segundo? Megabytes por segundo de disco lê e grava? Utilização da CPU? Carga média? Uso de RAM?
Agora você pode começar a aprender sobre o desempenho do seu aplicativo correlacionando os dados, criando gráficos, etc. Você começará a ver padrões, a encontrar gargalos.
Você pode aprender que o seu sistema está em cerviz-garrafa
INSERT
eUPDATE
é em altas taxas de transação, apesar de bastante baixo / S de disco em megabytes por segundo. Isso sugere que você precisa melhorar o desempenho da liberação do disco com um controlador RAID de cache de write-back suportado por bateria ou alguns SSDs protegidos por energia de alta qualidade. Você também pode usarsynchronous_commit = off
se não houver problema em perder algumas transações na falha do servidor e / ou acommit_delay
, para retirar parte da carga de sincronização.Quando você faz um gráfico de suas transações por segundo com base no número de conexões simultâneas e corrige a taxa de solicitações variável que o aplicativo está vendo, poderá ter uma idéia melhor de onde está o ponto ideal da taxa de transferência.
Se você não possui armazenamento de liberação rápida (BBU RAID ou SSDs rápidos e duráveis), não desejará mais do que um número bastante pequeno de conexões de gravação ativa, talvez no máximo o dobro do número de discos que você possui, provavelmente menos dependendo da organização do RAID , desempenho do disco etc. Nesse caso, nem vale a pena tentativa e erro; basta atualizar seu subsistema de armazenamento para um com liberações rápidas de disco .
Procure
pg_test_fsync
uma ferramenta que ajude a determinar se isso pode ser um problema para você. A maioria dos pacotes do PostgreSQL instala essa ferramenta como parte do contrib, portanto você não precisa compilá-la. Se você receber menos do que um par de milhares de ops / segundo empg_test_fsync
que você urgentemente precisa atualizar o seu sistema de armazenamento. Meu laptop equipado com SSD recebe de 5000 a 7000. Minha estação de trabalho trabalhando com uma matriz RAID 10 de 4 discos de 7200 rpm SATA e write-through (sem cache de gravação) recebe cerca de 80 operações / segundof_datasync
, até 20 operações / segundofsync()
; é centenas de vezes mais lento . Compare: laptop com ssd vs estação de trabalho com gravação (sem gravação em cache) RAID 10. O SSD deste laptop é barato e eu não confio necessariamente nele para liberar seu cache de gravação em caso de perda de energia; Eu mantenho bons backups e não os utilizo para dados importantes. Os SSDs de boa qualidade têm o mesmo desempenho, se não melhor, e são duráveis para gravação.No caso de sua inscrição, recomendo fortemente que você analise:
UNLOGGED
tabelas para dados que você pode perder. Agregue-o periodicamente em tabelas registradas. Por exemplo, mantenha os jogos em andamento em tabelas não registradas e escreva as pontuações em tabelas duráveis comuns.commit_delay
(menos útil com armazenamento de descarga rápida - dica)synchronous_commit
transações que você pode perder (menos útil com armazenamento de descarga rápida - dica de dica)LISTEN
eNOTIFY
executar a invalidação de cache usando gatilhos nas tabelas do PostgreSQL.Em caso de dúvida: http://www.postgresql.org/support/professional_support/
fonte