Wie man den Sweet Spot zwischen Poolgröße und Datenbankverbindungen in PostgreSQL ermittelt


14

Wir haben Probleme, den Datenverkehr zu Stoßzeiten zu unserem Datenbankserver zu verarbeiten. Wir arbeiten an der Verbesserung der Hardware (siehe diese Frage zu diesem Thema), möchten aber auch an der Pooling-Konfiguration und der Server-Optimierung arbeiten.

Die Anwendung, an der wir arbeiten, ist ein rundenbasiertes Multiplayer-Spiel für Smartphones, bei dem das Backend aus Rails mit Unicorn und PostgreSQL 9.1 als Datenbank besteht. Wir haben derzeit 600 000 registrierte Benutzer und da der Spielstatus in der Datenbank gespeichert ist, werden alle paar Sekunden mehrere Tausend Schreibvorgänge ausgeführt. Wir haben die Logdateien von PostgreSQL mit PgBadger analysiert und in den kritischen Stunden bekommen wir eine Menge davon

FATAL: remaining connection slots are reserved for non-replication superuser connections

Die naive Lösung, um diesem Problem entgegenzuwirken, besteht darin, max_connections (derzeit 100) in postgresql.conf zu erhöhen . Ich habe http://wiki.postgresql.org/wiki/Number_Of_Database_Connections gelesen, was darauf hinweist, dass dies möglicherweise nicht das Richtige ist. In dem oben erwähnten Artikel wird es um das Finden der Sweet Spot zwischen max_connections und bezeichnet Poolgröße .

Was kann getan werden, um diesen Sweet Spot zu finden? Gibt es gute Werkzeuge , um die I / O - Leistung für verschiedene Werte von messen max_connections und Pool - Größe ?

Unser aktuelles Setup besteht aus 4 Spieleservern mit jeweils 16 Einhornarbeitern und einer Poolgröße von 5.

Hier sind die nicht standardmäßigen Postgres-Einstellungen, die wir verwenden:

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

Sind Sie die Person, die in den letzten Wochen auf der Mailingliste danach gefragt hat? In diesem Fall füge ich der Diskussion Backlinks hinzu. Außerdem: Welche Hardware und Konfiguration haben Sie für den DB-Server ? wiki.postgresql.org/wiki/Slow_Query_Questions . Nicht-Standardeinstellungen einschließen : wiki.postgresql.org/wiki/Server_Configuration . Haben Sie wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server gelesen ? Arbeiten Sie nach Möglichkeit in größeren Transaktionen? Verwenden Sie eine Caching-Ebene und wenn ja, welche? Benutzt du synchronous_commit = offoder a commit_delay?
Craig Ringer

Sie haben also insgesamt 20 Verbindungen zum PostgreSQL-Server? 5 pro Spielserver? Mit diesen 5 Conns von jedem Spielserver, die von 16 Einhornarbeitern geteilt werden?
Craig Ringer

Oh, protokollieren Sie langsame Abfragen? Wenn ja, was sind Ihre Hotspots? Einfaches INSERTs? Wie sieht Ihr Schema aus - ist es partitioniert? Was ist explain analyzemit einigen Beispielabfragen? Wie häufig sind Ihre Checkpoints und wie lange dauern sie? (Siehe Prüfpunktprotokollierungsoptionen). Und im Ernst, was ist Ihre PostgreSQL-Version ? (Update: Scheint, dass Sie Ihre Hardware hier auflisten : dba.stackexchange.com/questions/28061/… )
Craig Ringer

Was die Optimierung der Poolgröße angeht, müssen Sie zunächst eine zuverlässige Messung der Auslastung und des Durchsatzes des DB-Servers einrichten und dann die Einstellungen nach oben und unten vornehmen, bis Sie den optimalen Punkt gefunden haben.
Craig Ringer

@CraigRinger Nein, ich bin nicht diese Person. Aber danke für die Backlinks! Ich habe Tuning Your PostgreSQL Server gelesen und einige der genannten Tipps befolgt. Ich habe jetzt die nicht-Standardeinstellungen aufgenommen. Wir prüfen nun größere Transaktionen und Testssynchronous_commit = off
lorgartzor

Antworten:


14

Die kurze Antwort lautet "Versuch und Irrtum, geleitet von Überwachungs- und Leistungsmetriken".

Es gibt einige allgemeine Faustregeln, die Ihnen helfen sollen, den vagen Bereich zu finden, in dem Sie beginnen sollten, aber sie sind sehr allgemein. Die allgemeinen Richtlinien "Anzahl der CPUs plus Anzahl der unabhängigen Festplatten" werden oft zitiert, sind jedoch nur ein sehr grober Ausgangspunkt.

Was Sie wirklich tun müssen, ist eine zuverlässige Leistungsmessung für Ihre Anwendung. Starten Sie die Aufzeichnung von Statistiken.

Hierfür gibt es nicht viel integriertes Werkzeug. Es gibt Dinge wie das Nagios- check_postgresSkript, die Leistungsindikatorprotokollierung für Cacti-Systeme, den PostgreSQL-Statistikkollektor usw., aber es gibt nicht viel, das alles zusammenfügt. Leider musst du das selbst tun. Informationen zur PostgreSQL-Seite finden Sie unter Überwachung im PostgreSQL-Handbuch. Es gibt einige Optionen von Drittanbietern, z. B. den Postgres Enterprise Monitor von EnterpriseDB .

Für die hier genannten Metriken auf Anwendungsebene möchten Sie sie in gemeinsam genutzten Datenstrukturen oder in einer externen, nicht dauerhaften Datenbank wie Redis aufzeichnen und entweder beim Aufzeichnen oder vor dem Schreiben in Ihre PostgreSQL-Datenbank aggregieren. Der Versuch, direkt in Pg zu protokollieren, verzerrt Ihre Messungen mit dem durch die Aufzeichnung der Messungen verursachten Overhead und verschlimmert das Problem.

Die einfachste Option ist wahrscheinlich ein Singleton auf jedem App-Server, mit dem Sie Anwendungsstatistiken aufzeichnen. Sie möchten wahrscheinlich eine ständige Aktualisierung von min, max, n, total und mean durchführen. Auf diese Weise müssen Sie nicht jeden Statistikpunkt speichern, sondern nur die Aggregate. Dieser Singleton kann seine Gesamtstatistik alle x Minuten in Pg schreiben. Dies ist so niedrig, dass die Auswirkungen auf die Leistung minimal sind.

Beginnen mit:

  • Wie hoch ist die Anforderungslatenz? Mit anderen Worten, wie lange dauert es, bis die App eine Anfrage vom Client erhält, bis sie auf den Client antwortet. Erfassen Sie dies über einen Zeitraum hinweg und nicht als einzelne Aufzeichnungen. Gruppieren Sie es nach Anfragetyp. sagen wir, pro Seite.

  • Wie lange dauert der Datenbankzugriff für jede Abfrage oder jeden Abfragetyp, den die App ausführt? Wie lange dauert es, bis der DB Informationen abruft / speichert, bis er fertig ist und mit der nächsten Aufgabe fortfahren kann? Aggregieren Sie diese Statistiken erneut in der Anwendung und schreiben Sie nur die aggregierten Informationen in die Datenbank.

  • Wie ist Ihr Durchsatz? Wie viele Abfragen jeder Hauptklasse, die Ihre App ausführt, werden in x Minuten von der DB bearbeitet?

  • Wie viele Kundenanfragen gab es für denselben Zeitraum von x Minuten?

  • Wie viele DB-Verbindungen gab es, die alle paar Sekunden abgetastet und über dieselben x-Minuten-Fenster in der DB aggregiert wurden? Wie viele von ihnen waren untätig? Wie viele waren aktiv? In Beilagen? Aktualisierung? wählt? löscht? Wie viele Transaktionen gab es in diesem Zeitraum? Siehe die Dokumentation zum Statistikkollektor

  • Wie waren die Leistungsmetriken des Host-Systems, die wiederum über dasselbe Zeitintervall abgetastet und aggregiert wurden? Wie viele Lese- und wie viele Schreibzugriffe pro Sekunde? Megabyte pro Sekunde beim Lesen und Schreiben von Datenträgern? CPU-Auslastung? Durchschnittslast? RAM verbrauchen?

Sie können sich jetzt über die Leistung Ihrer App informieren, indem Sie die Daten korrelieren, grafisch darstellen usw. Sie sehen allmählich Muster und stellen Engpässe fest.

Möglicherweise stellen Sie fest, dass Ihr System überlastet ist INSERTund UPDATEhohe Transaktionsraten aufweist, obwohl die Datenträger-E / A in Megabyte pro Sekunde recht niedrig sind. Dies ist ein Hinweis darauf, dass Sie die Leistung beim Leeren der Festplatte mit einem akkugepufferten Write-Back-Caching-RAID-Controller oder einigen hochwertigen stromgeschützten SSDs verbessern müssen. Sie können auch verwenden, synchronous_commit = offwenn es in Ordnung ist, einige Transaktionen bei einem Serverabsturz zu verlieren und / oder einen commit_delayTeil der Synchronisierungslast zu entlasten.

Wenn Sie Ihre Transaktionen pro Sekunde in Abhängigkeit von der Anzahl der gleichzeitigen Verbindungen grafisch darstellen und die unterschiedliche Anforderungsrate der Anwendung berücksichtigen, können Sie besser erkennen, wo sich Ihr Durchsatz-Sweetspot befindet.

Wenn Sie keinen Fast-Flush-Speicher haben (BBU-RAID oder schnelle, langlebige SSDs), möchten Sie nicht mehr als eine relativ kleine Anzahl von aktiven Verbindungen, möglicherweise höchstens das Doppelte der Anzahl der Festplatten, die Sie haben, wahrscheinlich weniger, je nach RAID-Anordnung , Festplattenleistung usw. In diesem Fall ist es nicht einmal einen Versuch wert. Aktualisieren Sie einfach Ihr Speichersubsystem auf eines mit schneller Datenträgerspülung .

Suchen Sie pg_test_fsyncnach einem Tool, mit dem Sie feststellen können, ob dies ein Problem für Sie darstellt. Die meisten PostgreSQL-Pakete installieren dieses Tool als Teil von contrib, sodass Sie es nicht kompilieren müssen. Wenn Sie weniger als ein paar Tausend Operationen pro Sekunde ausführen, müssen pg_test_fsyncSie Ihr Speichersystem dringend aktualisieren. Mein mit SSD ausgestatteter Laptop bekommt 5000-7000. Mein - Arbeitsplatz bei der Arbeit mit einem 4-Platten RAID 10 - Array von 7200rpm SATA Platten und Write-Through (Nicht-Schreib-Caching) erhält etwa 80 ops / Sekunde in f_datasync, auf 20 ops / Sekunde fsync(); es ist hunderte Male langsamer . Vergleichen Sie : Laptop mit ssd vs Workstation mit Write-Through (Nicht-Schreib-Caching) RAID 10. Die SSD dieses Laptops ist billig und ich vertraue nicht unbedingt darauf, dass der Schreibcache bei Stromausfall geleert wird. Ich behalte gute Backups und würde sie nicht für Daten verwenden, die mir wichtig sind. Gute SSDs arbeiten genauso gut, wenn nicht sogar besser und sind beschreibbar.

Im Falle Ihrer Bewerbung rate ich Ihnen dringend, Folgendes zu prüfen:

  • Ein gutes Speichersubsystem mit schnellen Spülvorgängen. Ich kann das nicht genug betonen. Hochwertige stromausfallsichere SSDs und / oder ein RAID-Controller mit stromgeschütztem Write-Back-Cache.
  • Wenn Sie UNLOGGEDTabellen für Daten verwenden, können Sie es sich leisten, zu verlieren. Aggregieren Sie es regelmäßig in protokollierten Tabellen. Führen Sie beispielsweise Spiele in nicht protokollierten Tabellen fort und schreiben Sie die Ergebnisse in normale dauerhafte Tabellen.
  • Verwenden von a commit_delay(weniger nützlich bei schnell spülendem Speicher - Hinweis)
  • Deaktivieren synchronous_commitfür Transaktionen, die Sie sich leisten können, um zu verlieren (weniger nützlich bei schnellem Löschen von Speichern - Hinweis Hinweis)
  • Partitionierungstabellen, insbesondere Tabellen, in denen Daten "veralten" und bereinigt werden. Löschen Sie eine Partition, anstatt sie aus einer partitionierten Tabelle zu löschen.
  • Teilindizes
  • Reduzieren Sie die Anzahl der von Ihnen erstellten Indizes. Jeder Index hat Schreibkosten.
  • Stapelverarbeitung in größere Transaktionen
  • Verwenden schreibgeschützter Hot-Standby-Replikate, um die Leselast von der Hauptdatenbank zu entlasten
  • Verwenden einer Caching-Ebene wie memcached oder redis für Daten, die sich seltener ändern oder die es sich leisten können, veraltet zu sein. Sie können LISTENund verwenden NOTIFY, um die Cache-Invalidierung mithilfe von Triggern für PostgreSQL-Tabellen durchzuführen.

Im Zweifelsfall: http://www.postgresql.org/support/professional_support/

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.