Alta concorrência com PostgreSQL ou Fazendo uma manada de elefantes passar debaixo da porta Fábio Telles Rodriguez Timbira - A empresa brasileira de PostgreSQL 09 de novembro de 2012
Agenda Sobre o que estamos falando? Possíveis soluções Considerações finais Perguntas
Sobre esta apresentação esta apresentação está disponível em: http://www.timbira.com.br/material esta apresentação está sob licença Creative Commons Atribuição 3.0 Brasil: http://creativecommons.org/licenses/by/3.0/br
Sobre o que estamos falando? Figura: Metrô - SP / Estação Sé
Sobre o que estamos falando? Aplicações OLTP com alta concorrência: Milhares de conexões simultâneas; Vários usuários realizando gravações nas mesmas tabelas; Várias usuários consultando informações que acabaram de ser gravadas; Cada usuário deve ser atendido em tempo hábil; Crescimento de vários GBs por dia.
Tratamento Multi Documentos - TMD Tratamento de imagens descentralizado em ambiente bancario: Crescimento de 5GB a 20GB por dia; Até 2 milhões documentos tratados por dia; Mais de 5 mil agências com 10 mil estações de captura. Pool de 25 servidores com complementação automática; Mais de 500 estações de complementação manual; Centenas de regras de negócio aplicadas para diversos tipos de documento em diversas etapas (workflow); Troca de informações em lote com Mainframe; Troca de informações em XML com outros sistemas legados; Exportação de arquivos de saída. TUDO AO MESMO TEMPO, com janela de 6 horas de processamento.
Gargalo de CPU Figura: Trem em Mulan - Paquistão
Gargalo de CPU SO não trabalha bem com mais de 700 processos simultâneos; O custo para gerenciar a fila de espera só aumenta o problema; Cada conexão precisa de memória, keep alive pela rede e semaforização; O número de conexões ativas no SGDB deve ficar na órdem de 2 para cada core; Aplicações server podem utilizar conexões persistentes...... as aplicações client NÃO;
Lock Inferno Figura: Cruzamento das Avenidas Faria Lima com a Juscelino Kubitschek
Problemas com a modelagem Modelagem de dados ruim pode levar anos para revelar um resultado ruim. Leva horas para mostrar a catástrofe em alta concorrência;
Agenda Sobre o que estamos falando? Possíveis soluções Considerações finais Perguntas
Controlando o número de conexões PGBouncer: 1 Pool de conexões para transações no modo transaction; 1 Pool de conexões para consultas no modo statement; Aumento na eficiencia do processador, fila de espera das transações diminui; PGmemcache Replicas de dados do PostgreSQL para SQLite nas estações utiliza memcache; Um gatilho nas tabelas replicadas atualiza o número de versão do cache; Ao solicitar uma réplica, a estação compara a sua versão da tabela com a versão do cache; Poderia ser implementado com Listem / Notify
Locks Só abra uma transação, se realmente precisar; Saiba quando abrir e quando fechar uma transação; Não se perca na aplicação; Se abrir, feche logo. Não espere eventos for a do SGDB para fechar sua transação; Não utilize SELECT... FOR UPDATE; Não utilize LOCKs expĺıcitos. Tire proveito do MVCC; DEAD LOCK são problemas de lógica da aplicação. Altere a lógica dela;
Ajustes de Hardware CPU rápida é menos importante que ter muitos cores; Muita memória RAM para manter um númer alto de conexões; Use cache de disco para suportar um grande volume de gravações concorrentes; Discos rápidos e separados para o pg xlog é imprecindível;
Ajustes no SO (Linux) /etc/sysctl.conf kernel.shmmax (25% da RAM disponível) Semáforos (para suportar um número alto de conexões) file-max overcommit /etc/security/limits.conf nproc nofile /etc/fstab noatime para os dados noatime + writeback para o pg xlog
Ajustes no PostgreSQL max connections O menor número viável; Faça o possível para diminuir este valor para menos de 500; pg hba.conf Limite ao máximo a origem das suas conexões; Limite os usuários e bases que eles vão se conectar; Rejeite usuários, grupos e redes desconhecidos;
Ajustes no PostgreSQL shared buffers < 8GB ou 20% da RAM disponível (o que for maior); autovacuum em tabelas que sofrem cargas pesadas em lote, desligue; Memória por processo temp buffer < 16MB work mem < 16MB Ajuste individualmente conexões específicas; checkpoint segments Aumente para pelo menos 16 Limite de acordo com tempo que o recover pode levar
Acerte a sua modelagem Use o tipo de dados certo para a tarefa certa; Use chaves naturais; Não use campos flex; Para dados não estruturados, você tem hstore, vetores e tipos compostos; Use índices e gatilhos com sabedoria (teste e monitore o seu uso); Pilhas e filas não devem ficar no seu SGDB;
Escrevendo SQL Jamais utilize uma função em PL para algo que um SQL puro consegue fazer; COMMIT a cada X alterações. X > 100 e < 100K; Se uma consulta retorna mais de 100 registros, reveja a regra de negócio; INSERT < INSERT multiplo < PREPARE e EXECUTE < COPY < INSERT... SELECT Aprenda a usar subconsultas e window functions e Common Table Expression; Relatórios pesados devem utilizar visões materializadas.
Agenda Sobre o que estamos falando? Possíveis soluções Considerações finais Perguntas
Testes Teste as funcionalidades Teste com volumes de dados o mais realistas possível Teste com carga de concorrência o mais realista possível
Rollout Como testes com volume de dados e concorrência nunca são bons... Faça o deploy de poucas funcionalidades por vêz; Adicione novos usuários aos poucos; Esteja preparado para o caos durante o rollout; Não tente matar mais de um leão por dia; O rollout de uma única parte do sistema pode levar meses;
Monitoramento Monitore o SO, o PostgreSQL, a aplicação; Gere logs que mostrem a operação e a duração de cada ação; Gere logs em formatos que possam ser manipulados por ferramentas automatizadas; Aprenda a configurar o log do PostgreSQL e o PGBadger; Faça coletas periódicas e armazene tudo em um local central; Crie baselines e compare sempre com elas;
Para os DBAs... Durma bem antes de um novo deploy. Tire uns dias de folga; Não deixe de tomar cerveja com os amigos... Pratique exercícios físicos regularmente!!!
Perguntas? Fábio Telles Rodriguez telles@timbira.com.br http://www.timbira.com.br