Cómo determinar el punto óptimo entre el tamaño del grupo y las conexiones de la base de datos en PostgreSQL


14

Tenemos problemas para manejar el tráfico durante las horas pico a nuestro servidor de base de datos. Estamos buscando mejorar el hardware (vea esta pregunta sobre ese lado de las cosas ) pero también queremos trabajar en la configuración de agrupación y el ajuste del servidor.

La aplicación en la que estamos trabajando es un juego multijugador por turnos para teléfonos inteligentes, donde el backend consiste en Rails con unicornio y PostgreSQL 9.1 como base de datos. Actualmente tenemos 600 000 usuarios registrados y, dado que el estado del juego se almacena en la base de datos, se realizan varios miles de escrituras cada dos segundos. Hemos analizado los archivos de registro de PostgreSQL usando PgBadger y durante las horas críticas obtenemos una gran cantidad de

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

La solución ingenua para contrarrestar este problema sería aumentar max_ connections (que actualmente es 100) en postgresql.conf . He leído http://wiki.postgresql.org/wiki/Number_Of_Database_Connections que indica que esto podría no ser lo correcto. En el artículo mencionado anteriormente, se hace referencia a encontrar el punto óptimo entre max_ connections y el tamaño de la agrupación .

¿Qué se puede hacer para encontrar este punto dulce? ¿Existen buenas herramientas para medir el rendimiento de E / S para diferentes valores de max_ connections y tamaño de grupo ?

Nuestra configuración actual es de 4 servidores de juegos, cada uno con 16 trabajadores de unicornio y un tamaño de grupo de 5.

Aquí están las configuraciones de postgres no predeterminadas que estamos usando:

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

¿Eres la persona que preguntó sobre esto en la lista de correo en las últimas semanas? Si es así, agregaré vínculos de retroceso a esa discusión. Además: ¿Cuál es el hardware y la configuración de su servidor DB ? wiki.postgresql.org/wiki/Slow_Query_Questions . Incluya configuraciones no predeterminadas: wiki.postgresql.org/wiki/Server_Configuration . ¿Has leído wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server ? ¿Agrupa el trabajo en transacciones más grandes cuando sea posible? ¿Utiliza una capa de almacenamiento en caché y, de ser así, qué? ¿Estás usando synchronous_commit = offo a commit_delay?
Craig Ringer el

¿Entonces tiene un total de 20 conexiones al servidor PostgreSQL? 5 por servidor de juego? ¿Con esos 5 conns de cada servidor de juegos compartidos entre 16 trabajadores de unicornio?
Craig Ringer

¿Estás registrando consultas lentas? Si es así, ¿cuáles son tus puntos calientes? INSERTS simple ? ¿Cómo es su esquema? ¿Está particionado? ¿Cuál es el explain analyzede algunas consultas de muestra? ¿Qué tan frecuentes son sus puntos de control y cuánto tardan? (Consulte las opciones de registro del punto de control). Y en serio, ¿cuál es tu versión de PostgreSQL ? (Actualización: Parece que enumeras tu hardware aquí: dba.stackexchange.com/questions/28061/… )
Craig Ringer

De todos modos, para el ajuste del tamaño del grupo específicamente, las únicas respuestas reales son configurar una medición robusta de la carga y el rendimiento del servidor de base de datos, luego comenzar a ajustar hacia arriba y hacia abajo hasta que encuentre el punto óptimo.
Craig Ringer

@CraigRinger No, no soy esa persona. Pero gracias por los vínculos de retroceso! He leído Tuning Your PostgreSQL server y seguí algunos de los consejos mencionados. Ahora he incluido la configuración no predeterminada. Ahora estamos considerando realizar transacciones y pruebas más grandessynchronous_commit = off
lorgartzor

Respuestas:


14

La respuesta breve aquí es "ensayo y error guiados por métricas de monitoreo y rendimiento".

Existen algunas reglas generales que deberían ayudarlo a encontrar el área vaga en la que debería comenzar, pero son muy generales. A menudo se citan las pautas generales "número de CPU más número de discos independientes", pero es solo un punto de partida increíblemente tosco.

Lo que realmente necesita hacer es obtener métricas de rendimiento sólidas para su aplicación. Comience a registrar estadísticas.

No hay mucho en el camino de herramientas integradas para esto. Hay cosas como el check_postgresscript nagios , el registro del contador de rendimiento del sistema Cacti, el recopilador de estadísticas PostgreSQL, etc., pero no hay mucho que lo reúna todo. Lamentablemente, tendrás que hacer eso mismo. Para el lado de PostgreSQL, vea monitoreo en el manual de PostgreSQL. Existen algunas opciones de terceros, como Postgres Enterprise Monitor de EnterpriseDB .

Para las métricas de nivel de aplicación mencionadas aquí, querrá registrarlas en estructuras de datos compartidas o en una base de datos externa no duradera como Redis y agregarlas a medida que las registra o antes de escribirlas en su base de datos PostgreSQL. Intentar iniciar sesión directamente en Pg distorsionará sus mediciones con la sobrecarga creada al registrar las mediciones y empeorará el problema.

La opción más simple es probablemente un singleton en cada servidor de aplicaciones que use para registrar las estadísticas de la aplicación. Probablemente desee mantener una actualización constante min, max, n, total y media; de esa manera no tiene que almacenar cada punto de estadística, solo los agregados. Este singleton puede escribir sus estadísticas agregadas en Pg cada x minutos, una tasa lo suficientemente baja como para que el impacto en el rendimiento sea mínimo.

Empezar con:

  • ¿Cuál es la latencia de solicitud? En otras palabras, cuánto tiempo tarda la aplicación en recibir una solicitud del cliente hasta que responde al cliente. Registre esto en conjunto durante un período de tiempo, en lugar de como registros individuales. Agrúpelo por tipo de solicitud; digamos, por página.

  • ¿Cuál es el retraso de acceso a la base de datos para cada consulta o tipo de consulta que ejecuta la aplicación? ¿Cuánto tiempo lleva pedirle a la base de datos información / almacenar información hasta que esté lista y pueda pasar a la siguiente tarea? Nuevamente, agregue estas estadísticas en la aplicación y solo escriba la información agregada en la base de datos.

  • ¿Cómo es tu rendimiento? En cualquier x minutos, ¿cuántas consultas de cada clase principal que ejecuta su aplicación reciben servicio de la base de datos?

  • Para ese mismo rango de tiempo de x minutos, ¿cuántas solicitudes de clientes hubo?

  • Tomando muestras cada pocos segundos y agregando sobre las mismas ventanas de x minutos en la base de datos, ¿cuántas conexiones de base de datos había? ¿Cuántos de ellos estaban ociosos? ¿Cuántos estaban activos? En insertos? Actualizaciones? selecciona? elimina? ¿Cuántas transacciones hubo durante ese período? Ver la documentación del recopilador de estadísticas

  • Nuevamente muestreando y agregando durante el mismo intervalo de tiempo, ¿cómo eran las métricas de rendimiento del sistema host? ¿Cuántas E / S de lectura y disco de escritura / segundo? ¿Megabytes por segundo de disco lee y escribe? ¿Utilización de la CPU? ¿Promedio de carga? Uso de RAM?

Ahora puede comenzar a aprender sobre el rendimiento de su aplicación correlacionando los datos, graficando, etc. Comenzará a ver patrones, comenzará a encontrar cuellos de botella.

Es posible que se entere de que su sistema tiene un cuello de botella INSERTy UPDATEestá a altas tasas de transacción, a pesar de las E / S de disco bastante bajas en megabytes por segundo. Este sería un indicio de que necesita mejorar el rendimiento del vaciado de disco con un controlador RAID de almacenamiento en caché de escritura de respaldo con batería o algunos SSD de alta calidad con protección de energía. También podría usar synchronous_commit = offsi está bien perder algunas transacciones en caso de bloqueo del servidor, y / o a commit_delay, para quitar parte de la carga de sincronización.

Cuando grafica tus transacciones por segundo contra el número de conexiones concurrentes y corrige la tasa de solicitud variable que está viendo la aplicación, podrás tener una mejor idea de dónde está tu punto óptimo de rendimiento.

Si no tiene almacenamiento de descarga rápida (BBU RAID o SSD rápidos y duraderos), no querrá más que un número bastante pequeño de conexiones de escritura activa, tal vez como máximo el doble de la cantidad de discos que tiene, probablemente menos dependiendo de la disposición de RAID , rendimiento del disco, etc. En este caso ni siquiera vale la pena probarlo y equivocarlo; simplemente actualice su subsistema de almacenamiento a uno con descargas rápidas de disco .

Busque pg_test_fsyncuna herramienta que lo ayudará a determinar si esto podría ser un problema para usted. La mayoría de los paquetes de PostgreSQL instalan esta herramienta como parte de contrib, por lo que no debería necesitar compilarla. Si obtiene menos de un par de miles de operaciones / segundo pg_test_fsync, necesita actualizar urgentemente su sistema de almacenamiento. Mi portátil equipado con SSD obtiene 5000-7000. Mi estación de trabajo en el trabajo con una matriz RAID 10 de 4 discos de discos SATA de 7200 rpm y escritura a través (almacenamiento en caché sin escritura) obtiene aproximadamente 80 operaciones / segundo f_datasync, hasta 20 operaciones / segundo para fsync(); Es cientos de veces más lento . Compare: computadora portátil con SSD vs estación de trabajo con escritura (no-caché de escritura) RAID 10. El SSD de este portátil es barato y no confío necesariamente en que vacie su caché de escritura en caso de pérdida de energía; Mantengo buenas copias de seguridad y no las usaría para los datos que me interesan. Los SSD de buena calidad funcionan igual de bien, si no mejor, y son durables para escritura.

En el caso de su solicitud, le recomiendo encarecidamente que investigue:

  • Un buen subsistema de almacenamiento con descargas rápidas. No puedo enfatizar esto lo suficiente. SSD de buena calidad a prueba de fallas de energía y / o un controlador RAID con memoria caché de escritura protegida.
  • Usando UNLOGGEDtablas para datos que puede permitirse perder. Agregue periódicamente en tablas registradas. Por ejemplo, mantenga los juegos en progreso en tablas no registradas y escriba los puntajes en tablas duraderas comunes.
  • Usar un commit_delay(menos útil con almacenamiento de descarga rápida - pista)
  • Desactivar las synchronous_committransacciones que puede permitirse perder (menos útil con el almacenamiento de descarga rápida: pista)
  • Tablas de partición, especialmente tablas donde los datos "caducan" y se limpian. En lugar de eliminar de una tabla particionada, suelte una partición.
  • Índices parciales
  • Reduciendo la cantidad de índices que crea. Cada índice tiene un costo de escritura.
  • Lote de trabajo en transacciones más grandes
  • Uso de réplicas en espera activa de solo lectura para quitar la carga de lectura de la base de datos principal
  • Usar una capa de almacenamiento en caché como memcached o redis para datos que cambian con menos frecuencia o que pueden permitirse ser obsoletos. Puede usar LISTENy NOTIFYrealizar la invalidación de caché utilizando desencadenadores en tablas PostgreSQL.

En caso de duda: http://www.postgresql.org/support/professional_support/

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.