PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Leistungssteigerung für PostgreSQL mit HAProxy

Die Datenbankleistung ist ein sehr wichtiges Anliegen bei der Wartung Ihres Datenbankclusters, insbesondere wenn es mit der Zeit wächst. Dies gilt insbesondere dann, wenn Ihre Anwendung zunächst mit geringem Datenverkehr begann und dann auf mittlere oder hohe Lese-/Schreib-Workloads anwächst.

Denken Sie daran, dass es keine perfekte Konfiguration gibt, auf die Sie sich lange verlassen können, da sich bestimmte Workloads im Laufe der Zeit ändern können.

Mit ClusterControl führt das Erstellen oder Bereitstellen eines neuen PostgreSQL-Datenbank-Clusters eine grundlegende Analyse durch, wie z. B. das Überprüfen Ihrer Hardwareressourcen, wendet dann die automatische Optimierung an und legt die Werte für die ausgewählten einstellbaren Parameter fest. Mit der Weiterentwicklung von PostgreSQL wurden auch viele Tools entwickelt, um verschiedene Konfigurationen zu unterstützen, insbesondere für den Lastausgleich.

In diesem Blog werfen wir einen Blick auf die Bedeutung von HAProxy und wie es zur Leistungssteigerung beitragen kann. Es ist ein altes Tool, aber dennoch ein leistungsstarker Proxy und/oder Load Balancer, der nicht nur Datenbankserver, sondern auch netzwerkanwendungsspezifische Protokolle unterstützt. HAProxy kann über Schicht vier bzw. Schicht sieben arbeiten, abhängig von der Art des Setups basierend auf der Konfiguration.

PostgreSQL-Leistungsoptimierung

Einer der Hauptfaktoren für die Leistungssteigerung von PostgreSQL beginnt mit der grundlegenden Parameterabstimmung von initdb zu Laufzeitparameterwerten. Dieser muss in der Lage sein, die gewünschte Arbeitslast gemäß Ihren bestimmten Anforderungen zu bewältigen. Bevor wir uns auf den Weg zum HAProxy-Feature für PostgreSQL machen können, muss Ihr Datenbankserver stabil und auf die gewünschten Variablen eingestellt sein. Lassen Sie uns eine Liste von PostgreSQL-Bereichen erstellen, in denen es um Dinge geht, die sich auf die Leistung Ihres Datenbankservers auswirken können.

Tuning für eine praktikable Speicherverwaltung

PostgreSQL ist effizient und kann effektiv in nur 256 MB Arbeitsspeicher ausgeführt werden. Speicher ist nicht teuer, aber die meisten Datensätze sind kleiner als 4 GB. Wenn Sie mindestens 4 GB haben, kann Ihr aktiver Datensatz im Datei- und/oder Shared_buffer-Cache verbleiben.

Das Optimieren Ihres PostgreSQL für die Speicherverwaltung ist eines der wichtigsten und grundlegendsten Dinge, die Sie einstellen müssen. Die richtige Einstellung kann sich auf die Leistungssteigerung Ihres Datenbankservers auswirken. Obwohl es davon abhängt, mit welcher Art von Tischen Sie spielen. Schlechte Abfragen und schlechte Tabellendefinitionen können ebenfalls zu schlechter Leistung führen. Wenn die richtigen Indizes für Ihre Tabellen definiert sind und Abfragen auf Indizes verweisen, können die Chancen zwischen 80 % und 100 % der Abfragen aus Ihrem Speicher abgerufen werden. Dies insbesondere, wenn der Indexpuffer den richtigen Wert hat, um Ihren in Ihren Tabellen definierten Index zu laden. Schauen wir uns die Parameter an, die üblicherweise zur Leistungsverbesserung eingestellt werden.

  • shared_buffers - PostgreSQL dimensioniert seinen Hauptspeicherplatz mit shared_buffers. Der Arbeitscache aller heißen Tupel (und Indexeinträge) in PostgreSQL. Dieser Parameter legt die Speichermenge fest, die der Datenbankserver für gemeinsam genutzte Speicherpuffer verwendet. Es ist ein vorab zugewiesener Cache (Puffer). Für Linux-basierte Systeme ist es ideal, den Kernel-Parameter kernel.shmmax zu setzen, der dauerhaft über die Kernel-Konfigurationsdatei /etc/sysctl.conf gesetzt werden kann.
  • temp_buffers - Legt die maximale Anzahl temporärer Puffer fest, die für jede Sitzung verwendet werden. Dies sind lokale Sitzungspuffer, die nur für den Zugriff auf temporäre Tabellen verwendet werden. Eine Sitzung weist die temporären Puffer nach Bedarf bis zu dem von temp_buffers angegebenen Limit zu.
  • work_mem - Der für Arbeitsoperationen verfügbare Arbeitsspeicher (Sortierungen), bevor PostgreSQL auslagert. Nicht global festlegen (postgresql.conf). Verwenden Sie pro Transaktion, da dies pro Abfrage, pro Verbindung oder pro Sortierung schlecht sein kann. Es wird empfohlen, EXPLAIN ANALYZE zu verwenden, um zu sehen, ob Sie überlaufen oder nicht.
  • maintenance_work_mem - Gibt die Speichermenge an, die für Wartungsvorgänge verwendet werden soll (VACUUM, CREATE INDEX und ALTER TABLE … ADD FOREIGN KEY …)

Tuning für eine praktikable Datenträgerverwaltung

Eine Reihe von Laufzeitparametern, die hier eingestellt werden können. Lassen Sie uns diese auflisten:

  • temp_file_limit - Gibt die maximale Menge an Speicherplatz an, die eine Sitzung für temporäre Dateien verwenden kann, z. B. temporäre Sortier- und Hash-Dateien oder die Speicherdatei für einen gehaltenen Cursor. Eine Transaktion, die versucht, dieses Limit zu überschreiten, wird storniert.
  • fsync - Wenn fsync aktiviert ist, versucht PostgreSQL sicherzustellen, dass die Updates physisch auf die Festplatte geschrieben werden. Dadurch wird sichergestellt, dass der Datenbank-Cluster nach einem Betriebssystem- oder Hardware-Crash wieder in einen konsistenten Zustand versetzt werden kann. Während das Deaktivieren von fsync im Allgemeinen die Leistung verbessert, kann es im Falle eines Stromausfalls oder eines Systemabsturzes zu Datenverlust kommen. Daher ist es nur ratsam, fsync zu deaktivieren, wenn Sie Ihre gesamte Datenbank problemlos aus externen Daten neu erstellen können
  • synchronous_commit – Wird verwendet, um zu erzwingen, dass Commit darauf wartet, dass WAL auf die Festplatte geschrieben wird, bevor ein Erfolgsstatus an den Client zurückgegeben wird. Diese Variable hat Kompromisse zwischen Leistung und Zuverlässigkeit. Wenn Sie mehr Leistung benötigen, stellen Sie dies auf Aus, was bedeutet, dass bei Serverabstürzen die Tendenz zu Datenverlusten besteht. Wenn die Zuverlässigkeit wichtig ist, setzen Sie dies andernfalls auf Ein. Dies bedeutet, dass zwischen dem Erfolgsstatus und einem garantierten Schreibvorgang auf die Festplatte eine Zeitlücke besteht, was die Leistung beeinträchtigen kann.
  • checkpoint_timeout, checkpoint_completion_target - PostgreSQL schreibt Änderungen in WAL, was eine teure Operation ist. Wenn häufig Änderungen in WAL geschrieben werden, kann dies die Leistung beeinträchtigen. So funktioniert es, der Checkpoint-Prozess löscht die Daten in die Datendateien. Diese Aktivität wird ausgeführt, wenn CHECKPOINT auftritt, und kann eine große Menge an E/A verursachen. Dieser ganze Prozess beinhaltet teure Lese-/Schreiboperationen auf der Festplatte. Sie (Admin-Benutzer) können CHECKPOINT jedoch immer dann ausgeben, wenn es notwendig erscheint, oder es automatisieren, indem Sie die gewünschten Werte für diese Parameter festlegen. Der Parameter checkpoint_timeout wird verwendet, um die Zeit zwischen WAL-Prüfpunkten festzulegen. Eine zu niedrige Einstellung verringert die Wiederherstellungszeit nach einem Absturz, da mehr Daten auf die Festplatte geschrieben werden, aber es beeinträchtigt auch die Leistung, da jeder Checkpoint wertvolle Systemressourcen verbraucht. checkpoint_completion_target ist der Bruchteil der Zeit zwischen Checkpoints für den Checkpoint-Abschluss. Eine hohe Anzahl von Prüfpunkten kann die Leistung beeinträchtigen. Für reibungsloses Checkpointing muss checkpoint_timeout ein niedriger Wert sein. Andernfalls sammelt das Betriebssystem alle schmutzigen Seiten, bis das Verhältnis erreicht ist, und macht dann einen großen Flush.

Andere Parameter für die Leistung optimieren

Es gibt bestimmte Parameter, die die Leistung von PostgreSQL steigern und vorantreiben. Lassen Sie uns diese unten auflisten:

  • wal_buffers - PostgreSQL schreibt seinen WAL-Eintrag (Write Ahead Log) in die Puffer und diese Puffer werden dann auf die Festplatte geleert. Die Standardgröße des Puffers, definiert durch wal_buffers, ist 16 MB, aber wenn Sie viele gleichzeitige Verbindungen haben, kann ein höherer Wert eine bessere Leistung bringen.
  • effektive_cache_größe - Die Effective_Cache_Size bietet eine Schätzung des für das Disk-Caching verfügbaren Speichers. Es handelt sich lediglich um eine Richtlinie, nicht um die genau zugewiesene Speicher- oder Cache-Größe. Es weist keinen tatsächlichen Speicher zu, sondern teilt dem Optimierer die im Kernel verfügbare Cache-Menge mit. Wenn der Wert zu niedrig eingestellt ist, kann der Abfrageplaner entscheiden, einige Indizes nicht zu verwenden, auch wenn sie hilfreich wären. Daher ist es immer vorteilhaft, einen großen Wert einzustellen.
  • default_statistics_target - PostgreSQL sammelt Statistiken aus jeder der Tabellen in seiner Datenbank, um zu entscheiden, wie Abfragen darauf ausgeführt werden. Standardmäßig sammelt es nicht zu viele Informationen, und wenn Sie keine guten Ausführungspläne erhalten, sollten Sie diesen Wert erhöhen und dann ANALYZE in der Datenbank erneut ausführen (oder auf das AUTOVACUUM warten).

Effizienz von PostgreSQL-Abfragen 

PostgreSQL hat eine sehr leistungsfähige Funktion zur Optimierung von Abfragen. Mit dem eingebauten Genetic Query Optimizer (bekannt als GEQO). Es verwendet einen genetischen Algorithmus, der eine heuristische Optimierungsmethode durch randomisierte Suche ist. Dies wird angewendet, wenn eine Optimierung mit JOINs durchgeführt wird, was eine sehr gute Leistungsoptimierung bietet. Jeder Kandidat im Join-Plan wird durch eine Sequenz dargestellt, in der die Basisbeziehungen zu verbinden sind. Es führt nach dem Zufallsprinzip eine genetische Beziehung durch, indem es einfach eine mögliche Verbindungssequenz generiert, aber nach dem Zufallsprinzip.

Für jede betrachtete Join-Sequenz wird der Standardplanercode aufgerufen, um die Kosten für die Durchführung der Abfrage unter Verwendung dieser Join-Sequenz zu schätzen. Somit haben alle für jede der JOIN-Sequenzen ihre anfangs bestimmten Beziehungs-Scan-Pläne. Dann berechnet der Abfrageplan den praktikabelsten und leistungsfähigsten Plan, d. h. mit niedrigeren geschätzten Kosten, und wird als "passender" angesehen als die mit höheren Kosten.

Da es über eine leistungsstarke Funktion verfügt, die in PostgreSQL integriert ist, und die richtig konfigurierten Parameter gemäß Ihren gewünschten Anforderungen, beeinträchtigt es die Machbarkeit in Bezug auf die Leistung nicht, wenn die Last nur auf a geworfen wird primärer Knoten. Load-Balancing mit HAProxy trägt zu noch mehr Leistung für PostgreSQL bei.

Leistungssteigerung für PostgreSQL mit Read-Write-Splitting 

Möglicherweise haben Sie eine großartige Leistung im Umgang mit Ihrem PostgreSQL-Serverknoten, aber Sie können möglicherweise nicht vorhersehen, welche Art von Arbeitslast Sie möglicherweise haben, insbesondere wenn hoher Datenverkehr eintritt und die Nachfrage die Grenzen überschreitet. Der Lastausgleich zwischen primär und sekundär bietet eine Leistungssteigerung innerhalb Ihrer Anwendung und/oder Clients, die eine Verbindung zu Ihrem PostgreSQL-Datenbankcluster herstellen. Wie dies bewerkstelligt werden kann, ist keine Frage mehr, da dies ein sehr übliches Setup für eine hohe Verfügbarkeit und Redundanz ist, wenn es darum geht, die Last zu verteilen und zu vermeiden, dass der primäre Knoten aufgrund von Hochlastverarbeitung festgefahren wird.

Die Einrichtung mit HAProxy ist einfach. Mit ClusterControl ist es jedoch effizienter, schneller und machbarer. Also verwenden wir ClusterControl, um dies für uns einzurichten.

PostgreSQL mit HAProxy einrichten

Dazu müssen wir lediglich HAProxy auf den PostgreSQL-Clustern installieren und einrichten. HAProxy hat eine Funktion zur Unterstützung von PostgreSQL durch die Option pgsql-check, aber seine Unterstützung ist eine sehr einfache Implementierung, um festzustellen, ob ein Knoten aktiv ist oder nicht. Es gibt keine Überprüfungen zum Identifizieren eines primären und eines Wiederherstellungsknotens. Eine Option ist die Verwendung von xinetd, für die wir uns darauf verlassen, dass der HAProxy über unseren xinetd-Dienst, der den Zustand eines bestimmten Knotens in unserem PostgreSQL-Cluster überprüft, kommuniziert.

Navigieren Sie unter ClusterControl wie unten beschrieben zu Manage → Load Balancer

Folgen Sie dann einfach basierend auf der Benutzeroberfläche im folgenden Screenshot. Sie können auf Erweiterte Einstellungen anzeigen klicken, um erweiterte Optionen anzuzeigen. Das Befolgen der Benutzeroberfläche ist jedoch sehr einfach. Siehe unten,

Ich importiere nur Einzelknoten-HAProxy ohne Redundanz, aber zum Zwecke von diesem Blog, lasst es uns einfacher machen.

Meine HAProxy-Beispielansicht ist unten gezeigt,

Wie oben gezeigt, sind 192.168.30.20 und 192.168.30.30 die primären bzw. Sekundär-/Wiederherstellungsknoten. Wohingegen der HAProxy im Sekundär-/Wiederherstellungsknoten installiert ist. Idealerweise installieren Sie Ihren HAProxy auf mehreren Knoten, um mehr Redundanz und hohe Verfügbarkeit zu haben. Am besten isolieren Sie ihn gegen die Datenbankknoten. Wenn Sie knapp bei Kasse sind oder Ihre Nutzung einsparen, können Sie sich dafür entscheiden, Ihre HAProxy-Knoten dort zu installieren, wo auch Ihre Datenbankknoten installiert sind.

ClusterControl richtet dies automatisch ein und beinhaltet auch den xinetd-Dienst für die PostgreSQL-Prüfung. Dies kann wie unten mit netstat überprüft werden,

[email protected]:~# netstat -tlv4np|grep haproxy

tcp        0      0 0.0.0.0:5433            0.0.0.0:*               LISTEN      28441/haproxy

tcp        0      0 0.0.0.0:5434            0.0.0.0:*               LISTEN      28441/haproxy

tcp        0      0 0.0.0.0:9600            0.0.0.0:*               LISTEN      28441/haproxy

Dabei ist Port 5433 schreibgeschützt und 5444 schreibgeschützt.

Für PostgreSQL suchen Sie nach dem xinetd-Dienst, nämlich postgreshk, wie unten gezeigt,

[email protected]:~# cat /etc/xinetd.d/postgreschk

# default: on

# description: postgreschk

service postgreschk

{

        flags           = REUSE

        socket_type     = stream

        port            = 9201

        wait            = no

        user            = root

        server          = /usr/local/sbin/postgreschk

        log_on_failure  += USERID

        disable         = no

        #only_from       = 0.0.0.0/0

        only_from       = 0.0.0.0/0

        per_source      = UNLIMITED

}

Die xinetd-Dienste verlassen sich auch auf /etc/services, sodass Sie möglicherweise den Port finden können, der für die Zuordnung vorgesehen ist.

[email protected]:~# grep postgreschk /etc/services

postgreschk        9201/tcp

Wenn Sie den Port Ihres Postgreschk auf den zuzuordnenden Port ändern müssen, müssen Sie diese Datei sowie die Dienstkonfigurationsdatei ändern und dann nicht vergessen, den xinetd-Daemon neu zu starten.

Der postgreschk-Dienst enthält einen Verweis auf eine externe Datei, die im Grunde eine Überprüfung auf Knoten durchführt, wenn sie beschreibbar ist, was bedeutet, dass es sich um eine primäre oder eine Master-Datei handelt. Wenn sich ein Knoten in der Wiederherstellung befindet, handelt es sich um eine Replik oder einen Wiederherstellungsknoten.

[email protected]:~# cat /usr/local/sbin/postgreschk

#!/bin/bash

#

# This script checks if a PostgreSQL server is healthy running on localhost. It will

# return:

# "HTTP/1.x 200 OK\r" (if postgres is running smoothly)

# - OR -

# "HTTP/1.x 500 Internal Server Error\r" (else)

#

# The purpose of this script is make haproxy capable of monitoring PostgreSQL properly

#



export PGHOST='localhost'

export PGUSER='s9smysqlchk'

export PGPASSWORD='password'

export PGPORT='7653'

export PGDATABASE='postgres'

export PGCONNECT_TIMEOUT=10



FORCE_FAIL="/dev/shm/proxyoff"



SLAVE_CHECK="SELECT pg_is_in_recovery()"

WRITABLE_CHECK="SHOW transaction_read_only"



return_ok()

{

    echo -e "HTTP/1.1 200 OK\r\n"

    echo -e "Content-Type: text/html\r\n"

    if [ "$1x" == "masterx" ]; then

        echo -e "Content-Length: 56\r\n"

        echo -e "\r\n"

        echo -e "<html><body>PostgreSQL master is running.</body></html>\r\n"

    elif [ "$1x" == "slavex" ]; then

        echo -e "Content-Length: 55\r\n"

        echo -e "\r\n"

        echo -e "<html><body>PostgreSQL slave is running.</body></html>\r\n"

    else

        echo -e "Content-Length: 49\r\n"

        echo -e "\r\n"

        echo -e "<html><body>PostgreSQL is running.</body></html>\r\n"

    fi

    echo -e "\r\n"



    unset PGUSER

    unset PGPASSWORD

    exit 0

}



return_fail()

{

    echo -e "HTTP/1.1 503 Service Unavailable\r\n"

    echo -e "Content-Type: text/html\r\n"

    echo -e "Content-Length: 48\r\n"

    echo -e "\r\n"

    echo -e "<html><body>PostgreSQL is *down*.</body></html>\r\n"

    echo -e "\r\n"



    unset PGUSER

    unset PGPASSWORD

    exit 1

}



if [ -f "$FORCE_FAIL" ]; then

    return_fail;

fi



# check if in recovery mode (that means it is a 'slave')

SLAVE=$(psql -qt -c "$SLAVE_CHECK" 2>/dev/null)

if [ $? -ne 0 ]; then

    return_fail;

elif echo $SLAVE | egrep -i "(t|true|on|1)" 2>/dev/null >/dev/null; then

    return_ok "slave"

fi



# check if writable (then we consider it as a 'master')

READONLY=$(psql -qt -c "$WRITABLE_CHECK" 2>/dev/null)

if [ $? -ne 0 ]; then

    return_fail;

elif echo $READONLY | egrep -i "(f|false|off|0)" 2>/dev/null >/dev/null; then

    return_ok "master"

fi



return_ok "none";

Die Benutzer/Passwort-Kombination muss eine gültige ROLE auf Ihrem PostgreSQL-Server sein. Da wir über ClusterControl installieren, wird dies automatisch gehandhabt.

Jetzt, da wir eine vollständige HAProxy-Installation haben, ermöglicht uns dieses Setup eine Lese-Schreib-Aufteilung, bei der Lese- und Schreibvorgänge an den primären oder beschreibbaren Knoten gehen, während nur Lesezugriff für primären und sekundären/ Wiederherstellungsknoten. Dieses Setup bedeutet nicht, dass es bereits leistungsfähig ist, es wurde noch wie zuvor besprochen mit einer Kombination aus HAProxy für den Lastenausgleich optimiert, um Ihrer Anwendung und den jeweiligen Datenbank-Clients mehr Leistungssteigerung zu verleihen.