Nous avons du mal à gérer le trafic pendant les heures de pointe vers notre serveur de base de données. Nous cherchons à améliorer le matériel (voir cette question à ce sujet ), mais nous voulons également travailler sur la configuration du pooling et le réglage du serveur.
L'application sur laquelle nous travaillons est un jeu multijoueur au tour par tour pour smartphones, où le backend se compose de Rails avec licorne et PostgreSQL 9.1 comme base de données. Nous avons actuellement 600 000 utilisateurs enregistrés et puisque l'état du jeu est stocké dans la base de données, plusieurs milliers d'écritures sont effectuées toutes les deux secondes. Nous avons analysé les fichiers journaux de PostgreSQL à l' aide de PgBadger et pendant les heures critiques, nous obtenons beaucoup de
FATAL: remaining connection slots are reserved for non-replication superuser connections
La solution naïve pour contrer ce problème serait d'augmenter max_connections (qui est actuellement de 100) dans postgresql.conf . J'ai lu http://wiki.postgresql.org/wiki/Number_Of_Database_Connections qui indique que ce n'est peut-être pas la bonne chose à faire. Dans l'article susmentionné, il est fait référence à la recherche du juste milieu entre max_connections et la taille du pool .
Que faire pour trouver ce sweet spot? Existe-t-il de bons outils pour mesurer les performances d'E / S pour différentes valeurs de max_connections et de taille de pool ?
Notre configuration actuelle est de 4 serveurs de jeu, chacun ayant 16 ouvriers licornes et une taille de pool de 5.
Voici les paramètres postgres non par défaut que nous utilisons:
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
la source
synchronous_commit = off
ou uncommit_delay
?INSERT
S simple ? À quoi ressemble votre schéma - est-il partitionné? Quelles sont lesexplain analyze
exemples de requêtes? Quelle est la fréquence de vos points de contrôle et combien de temps prennent-ils? (voir les options de consignation des points de contrôle). Et sérieusement, quelle est votre version de PostgreSQL ? (Mise à jour: Il semble que vous listiez votre matériel ici: dba.stackexchange.com/questions/28061/… )synchronous_commit = off
Réponses:
La réponse courte ici est "essais et erreurs guidés par des mesures de surveillance et de performances".
Il existe quelques règles générales qui devraient vous aider à trouver la zone vague dans laquelle vous devriez commencer, mais elles sont très générales. Les grandes lignes directrices «nombre de processeurs plus nombre de disques indépendants» sont souvent citées, mais ce n'est qu'un point de départ incroyablement grossier.
Ce que vous devez vraiment faire, c'est mettre en place des mesures de performances robustes pour votre application. Commencez à enregistrer les statistiques.
Il n'y a pas grand-chose en termes d'outils intégrés pour cela. Il y a des choses comme le
check_postgres
script nagios , la journalisation du compteur de performances du système Cacti, le collecteur de statistiques PostgreSQL, etc. Malheureusement, vous devrez le faire vous-même. Pour le côté PostgreSQL, voir la surveillance dans le manuel PostgreSQL. Certaines options tierces existent, comme Postgres Enterprise Monitor d'EnterpriseDB .Pour les mesures au niveau de l'application mentionnées ici, vous souhaiterez les enregistrer dans des structures de données partagées ou dans une base de données externe non durable comme Redis et les agréger soit au fur et à mesure que vous les enregistrez, soit avant de les écrire dans votre base de données PostgreSQL. Essayer de vous connecter directement à Pg faussera vos mesures avec la surcharge créée par l'enregistrement des mesures et aggravera le problème.
L'option la plus simple est probablement un singleton dans chaque serveur d'applications que vous utilisez pour enregistrer les statistiques des applications. Vous voulez probablement garder une mise à jour constante min, max, n, total et moyenne; de cette façon, vous n'avez pas à stocker chaque point de statistique, juste les agrégats. Ce singleton peut écrire ses statistiques agrégées sur Pg toutes les x minutes, un taux suffisamment bas pour que l'impact sur les performances soit minime.
Commencer avec:
Quelle est la latence des requêtes? En d'autres termes, combien de temps l'application prend-elle pour recevoir une demande du client jusqu'à ce qu'elle réponde au client. Enregistrez-les globalement sur une période de temps plutôt que sous forme d'enregistrements individuels. Regroupez-le par type de demande; disons, par page.
Quel est le délai d'accès à la base de données pour chaque requête ou type de requête que l'application exécute? Combien de temps faut-il pour demander à la base de données des informations / stocker des informations jusqu'à ce qu'elles soient terminées et pouvoir passer à la tâche suivante? Encore une fois, agrégez ces statistiques dans l'application et écrivez uniquement les informations agrégées dans la base de données.
Quel est votre débit? En x minutes, combien de requêtes de chaque classe principale exécutée par votre application sont traitées par la base de données?
Pour cette même plage de temps de x minutes, combien de demandes de clients y avait-il?
Échantillonnage toutes les quelques secondes et agrégation sur les mêmes fenêtres de x minutes dans la base de données, combien de connexions à la base de données y avait-il? Combien d'entre eux étaient inactifs? Combien étaient actifs? Dans les encarts? Mises à jour? sélectionne? supprime? Combien de transactions y a-t-il eu durant cette période? Voir la documentation du collecteur de statistiques
Encore une fois, l'échantillonnage et l'agrégation sur le même intervalle de temps, à quoi ressemblaient les mesures de performances du système hôte? Combien lisent et combien écrivent des E / S disque / seconde? Mégaoctets par seconde de lecture et d'écriture sur le disque? Utilisation du processeur? Charge moyenne? Utilisation de la RAM?
Vous pouvez maintenant commencer à vous renseigner sur les performances de votre application en corrélant les données, en les représentant graphiquement, etc. Vous commencerez à voir des modèles, à trouver des goulots d'étranglement.
Vous pouvez apprendre que votre système est limité
INSERT
et fonctionneUPDATE
à des taux de transaction élevés, malgré des E / S de disque assez faibles en mégaoctets par seconde. Ce serait un indice dont vous avez besoin pour améliorer vos performances de vidage de disque avec un contrôleur RAID de mise en cache à écriture différée alimenté par batterie ou certains SSD de haute qualité protégés par l'alimentation. Vous pouvez également utilisersynchronous_commit = off
si vous pouvez perdre quelques transactions en cas de panne du serveur et / oucommit_delay
, pour supprimer une partie de la charge de synchronisation.Lorsque vous représentez vos transactions par seconde par rapport au nombre de connexions simultanées et que vous corrigez le taux de demande variable que l'application voit, vous pourrez avoir une meilleure idée de l'endroit où se situe votre zone de débit idéale.
Si vous n'avez pas de stockage à vidage rapide (BBU RAID ou SSD durables rapides), vous ne voudrez pas plus qu'un nombre assez petit de connexions d'écriture active, peut-être au plus 2x le nombre de disques que vous avez, probablement moins selon l'arrangement RAID , les performances du disque, etc. Dans ce cas, cela ne vaut même pas la peine d'essais et d'erreurs; il suffit de mettre à niveau votre sous-système de stockage vers un avec des vidages de disque rapides .
Voir
pg_test_fsync
pour un outil qui vous aidera à déterminer si cela pourrait être un problème pour vous. La plupart des packages PostgreSQL installent cet outil dans le cadre de contrib, vous ne devriez donc pas avoir besoin de le compiler. Si vous obtenez moins de quelques milliers d'opérations / seconde,pg_test_fsync
vous devez d' urgence mettre à niveau votre système de stockage. Mon ordinateur portable équipé d'un SSD obtient de 5000 à 7000. Ma station de travail au travail avec une matrice RAID 10 à 4 disques de disques SATA à 7 200 tr / min et l'écriture directe (sans mise en cache en écriture) obtient environ 80 opérations / secondef_datasync
, jusqu'à 20 opérations / seconde pourfsync()
; c'est des centaines de fois plus lent . Comparatif: ordinateur portable avec SSD vs station de travail avec RAID 10 à écriture immédiate (sans mise en cache en écriture). Le SSD de cet ordinateur portable est bon marché et je ne lui fais pas nécessairement confiance pour vider son cache d'écriture en cas de coupure de courant; Je garde de bonnes sauvegardes et je ne l'utiliserais pas pour les données qui me tiennent à cœur. Les SSD de bonne qualité fonctionnent aussi bien sinon mieux et sont durables en écriture.Dans le cas de votre candidature, je vous conseille fortement de vous pencher sur:
UNLOGGED
tableaux pour les données que vous pouvez vous permettre de perdre. Agrégez-le périodiquement dans des tables enregistrées. Par exemple, gardez les jeux en cours dans des tables non enregistrées et écrivez les scores dans des tables durables ordinaires.commit_delay
(moins utile avec un stockage à vidage rapide - indice)synchronous_commit
pour les transactions que vous pouvez vous permettre de perdre (moins utile avec le stockage à vidage rapide - indice)LISTEN
etNOTIFY
pour effectuer l'invalidation du cache à l'aide de déclencheurs sur les tables PostgreSQL.En cas de doute: http://www.postgresql.org/support/professional_support/
la source