sql >> Base de Datos >  >> RDS >> PostgreSQL

Impulsando el rendimiento de PostgreSQL con HAProxy

El rendimiento de la base de datos es una preocupación muy importante al mantener su clúster de base de datos, especialmente a medida que crece con el tiempo. Esto es especialmente cierto si su aplicación comenzó con poco tráfico y luego creció a cargas de trabajo de lectura y escritura moderadas o pesadas.

Lo que debe recordar es que no existe una configuración perfecta en la que pueda confiar durante mucho tiempo, ya que ciertas cargas de trabajo pueden cambiar con el tiempo.

Con ClusterControl, la creación o implementación de un nuevo clúster de base de datos de PostgreSQL realiza un análisis básico, como verificar los recursos de hardware, luego aplica el ajuste automático y establece los valores para los parámetros ajustables seleccionados. A medida que PostgreSQL evoluciona, también se han desarrollado muchas herramientas para admitir diferentes configuraciones, especialmente para el equilibrio de carga.

En este blog, veremos la importancia de HAProxy y cómo puede ayudar a impulsar el rendimiento. Es una herramienta antigua, pero un poderoso proxy y/o equilibrador de carga que admite no solo servidores de bases de datos, sino también protocolos específicos de aplicaciones de red. HAProxy puede operar a través de la capa cuatro y la capa siete, respectivamente, según el tipo de configuración basada en la configuración.

Ajuste del rendimiento de PostgreSQL

Uno de los factores principales para impulsar el rendimiento de PostgreSQL comienza con el ajuste básico de los parámetros desde initdb hasta los valores de los parámetros de tiempo de ejecución. Esto tiene que ser capaz de manejar la carga de trabajo deseada de acuerdo con sus requisitos específicos. Antes de que podamos tomar el camino hacia la función HAProxy para PostgreSQL, su servidor de base de datos debe ser estable y estar ajustado a las variables deseadas. Tomemos una lista de áreas para PostgreSQL sobre qué cosas pueden afectar el rendimiento de su servidor de base de datos.

Ajuste para una gestión de memoria factible

PostgreSQL es eficiente y se puede ejecutar de manera efectiva con tan solo 256 Mb de memoria. La memoria no es costosa, pero la mayoría de los conjuntos de datos tienen menos de 4 Gib. Si tiene al menos 4 Gib, su conjunto de datos activo puede permanecer en el archivo y/o caché shared_buffer.

Afinar su PostgreSQL para la administración de memoria es una de las cosas más primarias y básicas que necesita configurar. Configurarlo adecuadamente puede impactar en el aumento del rendimiento de su servidor de base de datos. Aunque depende de con qué tipo de mesas estés jugando. Las consultas incorrectas y las definiciones de tablas deficientes también pueden generar un rendimiento deficiente. Con los índices adecuados definidos para sus tablas y con consultas que hacen referencia a los índices, las posibilidades pueden alcanzar del 80% al 100% de las consultas que se pueden recuperar de su memoria. Esto especialmente si el búfer de índice tiene el valor correcto para cargar su índice definido en sus tablas. Veamos los parámetros que se establecen comúnmente para mejorar el rendimiento.

  • búferes_compartidos - PostgreSQL dimensiona su espacio de memoria principal con shared_buffers. El caché de trabajo de todas las tuplas calientes (y entradas de índice) dentro de PostgreSQL. Este parámetro establece la cantidad de memoria que utiliza el servidor de la base de datos para los búferes de memoria compartida. Es un caché preasignado (búferes). Para los sistemas basados ​​en Linux, es ideal configurar el parámetro kernel kernel.shmmax, que se puede configurar de forma persistente a través del archivo de configuración del kernel /etc/sysctl.conf.
  • temp_buffers - Establece el número máximo de búferes temporales utilizados para cada sesión. Estos son búferes de sesión locales que se usan solo para acceder a tablas temporales. Una sesión asignará los búferes temporales según sea necesario hasta el límite dado por temp_buffers.
  • work_mem - La memoria de trabajo disponible para operaciones de trabajo (ordenaciones) antes de que PostgreSQL se intercambie. No establecer globalmente (postgresql.conf). Úselo por transacción, ya que esto puede ser incorrecto por consulta, por conexión o por clasificación. Se recomienda utilizar EXPLAIN ANALYZE para ver si se está desbordando o no.
  • mantenimiento_trabajo_mem - Especifica la cantidad de memoria que se utilizará para las operaciones de mantenimiento (VACUUM, CREATE INDEX y ALTER TABLE... ADD FOREIGN KEY...)

Ajuste para una administración de disco factible

Varios parámetros de tiempo de ejecución para establecer aquí. Vamos a enumerar cuáles son estos:

  • temp_file_limit - Especifica la cantidad máxima de espacio en disco que una sesión puede usar para archivos temporales, como archivos temporales de clasificación y hash, o el archivo de almacenamiento para un cursor retenido. Una transacción que intente exceder este límite será cancelada.
  • fsync - Si fsync está habilitado, PostgreSQL intentará asegurarse de que las actualizaciones se escriban físicamente en el disco. Esto garantiza que el clúster de la base de datos se pueda recuperar a un estado coherente después de un bloqueo del sistema operativo o del hardware. Si bien deshabilitar fsync generalmente mejora el rendimiento, puede causar la pérdida de datos en caso de una falla de energía o un bloqueo del sistema. Por lo tanto, solo es recomendable desactivar fsync si puede recrear fácilmente toda su base de datos a partir de datos externos
  • compromiso_sincrónico - Se utiliza para hacer cumplir que la confirmación esperará a que WAL se escriba en el disco antes de devolver un estado de éxito al cliente. Esta variable tiene compensaciones entre el rendimiento y la fiabilidad. Si necesita más rendimiento, desactívelo, lo que significa que cuando el servidor falla, hay tendencia a perder datos. De lo contrario, si la confiabilidad es importante, active esta opción. Esto significa que habrá un lapso de tiempo entre el estado de éxito y una escritura en disco garantizada, lo que puede afectar el rendimiento.
  • checkpoint_timeout, checkpoint_completion_target - PostgreSQL escribe cambios en WAL, lo cual es una operación costosa. Si escribe cambios con frecuencia en WAL, puede afectar negativamente el rendimiento. Entonces, cómo funciona, el proceso del punto de control vacía los datos en los archivos de datos. Esta actividad se realiza cuando ocurre CHECKPOINT y puede causar una gran cantidad de IO. Todo este proceso implica costosas operaciones de lectura/escritura de disco. Aunque usted (usuario administrador) siempre puede emitir CHECKPOINT cuando lo considere necesario o automatizarlo configurando los valores deseados para estos parámetros. El parámetro checkpoint_timeout se usa para establecer el tiempo entre los puntos de control WAL. Establecer esto en un valor demasiado bajo reduce el tiempo de recuperación de fallas, ya que se escriben más datos en el disco, pero también perjudica el rendimiento, ya que cada punto de control termina consumiendo valiosos recursos del sistema. checkpoint_completion_target es la fracción de tiempo entre los puntos de control para completar el punto de control. Una alta frecuencia de puntos de control puede afectar el rendimiento. Para que los puntos de control sean fluidos, checkpoint_timeout debe tener un valor bajo. De lo contrario, el sistema operativo acumulará todas las páginas sucias hasta que se alcance la proporción y luego buscará una gran descarga.

Ajuste de otros parámetros para el rendimiento

Existen ciertos parámetros que brindan impulso e impulsan el rendimiento en PostgreSQL. Vamos a enumerar cuáles son estos a continuación:

  • wal_buffers - PostgreSQL escribe su registro WAL (registro de escritura anticipada) en los búferes y luego estos búferes se vacían en el disco. El tamaño predeterminado del búfer, definido por wal_buffers, es de 16 MB, pero si tiene muchas conexiones simultáneas, un valor más alto puede brindar un mejor rendimiento.
  • tamaño_caché_efectivo - El tamaño_caché_efectivo proporciona una estimación de la memoria disponible para el almacenamiento en caché del disco. Es solo una guía, no la memoria exacta asignada o el tamaño de caché. No asigna memoria real, pero le dice al optimizador la cantidad de caché disponible en el núcleo. Si el valor de esto se establece demasiado bajo, el planificador de consultas puede decidir no usar algunos índices, incluso si serían útiles. Por lo tanto, establecer un valor grande siempre es beneficioso.
  • objetivo_de_estadísticas_predeterminado - PostgreSQL recopila estadísticas de cada una de las tablas de su base de datos para decidir cómo se ejecutarán las consultas sobre ellas. De forma predeterminada, no recopila demasiada información y, si no obtiene buenos planes de ejecución, debe aumentar este valor y luego ejecutar ANALYZE en la base de datos nuevamente (o esperar el AUTOVACUUM).

Eficiencia de consultas de PostgreSQL 

PostgreSQL tiene una característica muy poderosa para optimizar las consultas. Con el optimizador de consultas genéticas incorporado (conocido como GEQO). Utiliza un algoritmo genético que es un método de optimización heurística mediante búsqueda aleatoria. Esto se aplica cuando se realiza la optimización mediante JOIN, lo que proporciona una muy buena optimización del rendimiento. Cada candidato en el plan de unión está representado por una secuencia en la que unir las relaciones base. Realiza aleatoriamente una relación genética simplemente generando alguna posible secuencia de unión pero al azar.

Para cada secuencia de combinación considerada, se invoca el código del planificador estándar para estimar el costo de realizar la consulta usando esa secuencia de combinación. Entonces, para cada una de las secuencias JOIN, todas tienen sus planes de escaneo de relaciones determinados inicialmente. Luego, el plan de consulta calculará el plan más factible y eficaz, es decir, con un costo estimado más bajo y se considerará "más adecuado" que aquellos con un costo más alto.

Dado que tiene una función poderosa integrada dentro de PostgreSQL y los parámetros configurados adecuados de acuerdo con sus requisitos deseados, no anula la viabilidad en lo que respecta al rendimiento si la carga solo se lanza a un nodo primario. El equilibrio de carga con HAProxy ayuda aún más a impulsar el rendimiento de PostgreSQL.

Impulsar el rendimiento de PostgreSQL con división de lectura y escritura 

Es posible que tenga un gran rendimiento al tratar con su nodo de servidor PostgreSQL, pero es posible que no pueda anticipar qué tipo de carga de trabajo podría tener, especialmente cuando hay mucho tráfico y la demanda se sale de los límites. Equilibrar la carga entre una primaria y una secundaria proporciona un aumento del rendimiento dentro de su aplicación y/o clientes que se conectan a su clúster de base de datos PostgreSQL. Cómo se puede hacer esto ya no es una pregunta, ya que es una configuración muy común para una alta disponibilidad y redundancia cuando se trata de distribuir la carga y evitar que el nodo principal se atasque debido al procesamiento de alta carga.

La configuración con HAProxy es fácil. Sin embargo, es más eficiente, rápido y factible con ClusterControl. Así que usaremos ClusterControl para configurar esto para nosotros.

Configuración de PostgreSQL con HAProxy

Para hacer esto, solo tendremos que instalar y configurar HAProxy sobre los clústeres de PostgreSQL. HAProxy tiene una característica para soportar PostgreSQL a través de la opción pgsql-check pero su soporte es una implementación muy simple para determinar si un nodo está activo o no. No tiene comprobaciones para identificar un nodo principal y uno de recuperación. Una opción es usar xinetd para lo cual confiaremos en comunicar HAProxy para escuchar a través de nuestro servicio xinetd que verifica el estado de un nodo en particular en nuestro clúster de PostgreSQL.

Bajo ClusterControl, vaya a Administrar → Load Balancer tal como se muestra a continuación,

Luego simplemente siga según la IU según la captura de pantalla a continuación. Puede hacer clic en Mostrar configuración avanzada para ver más opciones avanzadas. Sin embargo, seguir la interfaz de usuario es muy sencillo. Véase más abajo,

Estoy importando HAProxy de un solo nodo sin redundancia pero con el propósito de este blog, hagámoslo más simple.

Mi muestra de vista HAProxy se muestra a continuación,

Como se muestra arriba, 192.168.30.20 y 192.168.30.30 son los principales y nodos secundarios/de recuperación respectivamente. Mientras que HAProxy está instalado en el nodo secundario/de recuperación. Idealmente, puede instalar su HAProxy en varios nodos para tener más redundancia y alta disponibilidad; lo mejor es aislarlo de los nodos de la base de datos. Si tiene un presupuesto ajustado o economiza su uso, puede optar por instalar sus nodos HAProxy, donde también se instalan los nodos de su base de datos.

ClusterControl configura esto automáticamente y también incluye el servicio xinetd para la comprobación de PostgreSQL. Esto se puede verificar con netstat como se muestra a continuación,

[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

Mientras que el puerto 5433 es de lectura y escritura y el 5444 es de solo lectura.

Para PostgreSQL, verifique el servicio xinetd, es decir, postgreshk, como se ve a continuación,

[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

}

Los servicios xinetd también se basan en /etc/services, por lo que es posible que pueda encontrar el puerto designado para mapear.

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

postgreschk        9201/tcp

Si necesita cambiar el puerto de su postgreschk a qué puerto asignar, también debe cambiar este archivo además del archivo de configuración del servicio y luego no olvide reiniciar el demonio xinetd.

El servicio postgreschk contiene una referencia a un archivo externo que básicamente verifica los nodos si se puede escribir, lo que significa que es principal o maestro. Si un nodo está en recuperación, entonces es una réplica o un nodo de recuperación.

[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";

La combinación de usuario/contraseña debe ser un ROL válido en su servidor PostgreSQL. Dado que estamos instalando a través de ClusterControl, esto se maneja automáticamente.

Ahora que tenemos una instalación completa de HAProxy, esta configuración nos permite tener una división de lectura y escritura donde las lecturas y escrituras van al nodo principal o de escritura, mientras que solo lectura tanto para el principal como para el secundario. nodos de recuperación. Esta configuración no significa que ya tenga un buen rendimiento, todavía se ha ajustado como se mencionó anteriormente con una combinación de HAProxy para el equilibrio de carga que agrega más rendimiento para su aplicación y los respectivos clientes de la base de datos.