Almacenamiento de métricas: cómo pasamos de Graphite+Whisper a Graphite+ClickHouse

¡Hola a todos! En su último artículo Escribí sobre la organización de un sistema de monitoreo modular para una arquitectura de microservicio. Nada se detiene, nuestro proyecto crece constantemente, al igual que la cantidad de métricas almacenadas. Cómo organizamos la transición de Graphite + Whisper a Graphite + ClickHouse en condiciones de alta carga, lea sobre las expectativas y los resultados de la migración bajo el corte.

Almacenamiento de métricas: cómo pasamos de Graphite+Whisper a Graphite+ClickHouse

Antes de contaros cómo organizamos la transición de almacenar métricas en Graphite + Whisper a Graphite + ClickHouse, me gustaría dar información sobre los motivos para tomar tal decisión y sobre las desventajas de Whisper con las que convivimos durante mucho tiempo.

Problemas de grafito+susurro

1. Alta carga en el subsistema de disco

En el momento de la transición, volamos hacia nosotros aproximadamente 1.5 millones de métricas por minuto. Con este flujo, la utilización del disco en los servidores fue de ~30 %. En general, fue bastante aceptable: todo funcionó de manera estable, se escribió rápidamente, se leyó rápidamente ... Hasta que uno de los equipos de desarrollo lanzó una nueva función y comenzó a enviarnos 10 millones de métricas por minuto. Fue entonces cuando el subsistema de disco se endureció y vimos una utilización del 100 %. El problema se resolvió rápidamente, pero el sedimento permaneció.

2. Falta de replicación y consistencia

Lo más probable es que, como todos los que usan / usaron Graphite + Whisper, hayamos vertido el mismo flujo de métricas en varios servidores Graphite a la vez para crear tolerancia a fallas. Y no hubo problemas especiales con esto, hasta el momento en que uno de los servidores no se cayó por alguna razón. A veces logramos recuperar el servidor caído lo suficientemente rápido y carbon-c-relay logró llenarlo con métricas de su caché, y otras veces no. Y luego hubo un agujero en las métricas, que cubrimos con rsync. El procedimiento fue bastante largo. Salvado solo por el hecho de que esto sucedió muy raramente. También tomamos periódicamente un conjunto aleatorio de métricas y las comparamos con otras similares en los nodos vecinos del clúster. En aproximadamente el 5% de los casos, varios valores diferían, lo que no nos hizo muy felices.

3. Gran cantidad de espacio ocupado

Dado que en Graphite escribimos no solo infraestructura, sino también métricas comerciales (y ahora también métricas de Kubernetes), a menudo nos encontramos con una situación en la que solo hay unos pocos valores en la métrica y el archivo .wsp se crea tomando tiene en cuenta todo el período de retención y ocupa una cantidad de espacio preasignada, que teníamos ~ 2 MB. El problema se ve agravado por el hecho de que a lo largo del tiempo aparecen muchos archivos de este tipo y, al crear informes sobre ellos, se necesita mucho tiempo y recursos para leer los puntos vacíos.

Me gustaría señalar de inmediato que los problemas descritos anteriormente se pueden tratar con varios métodos y con diversos grados de eficiencia, pero cuantos más datos comience a recibir, más se agravarán.

Teniendo todo lo anterior (teniendo en cuenta lo anterior) Artículo), así como un aumento constante en la cantidad de métricas recibidas, el deseo de transferir todas las métricas a un intervalo de almacenamiento de 30 segundos. (hasta 10 segundos si es necesario), decidimos probar Graphite+ClickHouse como una alternativa prometedora a Whisper.

Grafito+ClickHouse. Expectativas

Habiendo visitado varias reuniones de chicos de Yandex, habiendo leído un par de artículos sobre Habré, después de revisar la documentación y encontrar componentes sensatos para vincular ClickHouse con Graphite, ¡decidimos actuar!

Me gustaría obtener lo siguiente:

  • reducir la utilización del subsistema de disco del 30% al 5%;
  • reducir la cantidad de espacio ocupado de 1TB a 100GB;
  • poder recibir 100 millones de métricas por minuto en el servidor;
  • replicación de datos y tolerancia a fallas listas para usar;
  • no quedarse sentado en este proyecto durante un año y hacer la transición durante un período determinado;
  • cambiar sin tiempo de inactividad.

Bastante ambicioso, ¿verdad?

Grafito+ClickHouse. Componentes

Para recibir datos a través del protocolo Graphite y luego escribirlos en ClickHouse, elegí casa-click-de-carbono (golang).

Se eligió la última versión estable de ClickHouse 1.1.54253 como base de datos para almacenar series temporales. Al trabajar con él, surgieron problemas: una montaña de errores aparecían en los registros y no estaba del todo claro qué hacer con ellos. En discusión con Roman Lomonósov (autor de carbon-clickhouse, graphite-clickhouse y mucho más) se eligió el mayor versión 1.1.54236. Los errores desaparecieron: todo comenzó a funcionar a la perfección.

Para leer datos de ClickHouse se seleccionó clickhouse de grafito (golang). Como API para Graphite: carbonapi (golang). Para organizar la replicación entre tablas se utilizó ClickHouse cuidador del zoológico. Para las métricas de enrutamiento, dejamos nuestro amado relé-c-carbono (C) (ver artículo anterior).

Grafito+ClickHouse. Estructura de la mesa

“grafito” es una base de datos que creamos para monitorear tablas.

“graphite.metrics” es una tabla con el motor ReplicatedReplacingMergeTree (replicated Reemplazo de MergeTree). Esta tabla almacena los nombres de las métricas y las rutas a ellas.

CREATE TABLE graphite.metrics ( Date Date, Level UInt32, Path String, Deleted UInt8, Version UInt32 ) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/replicator/graphite.metrics', ‘r1’, Date, (Level, Path), 8192, Version);

“graphite.data” es una tabla con el motor ReplicatedGraphiteMergeTree (replicado GrafitoFusionarárbol). Esta tabla almacena valores métricos.

CREATE TABLE graphite.data ( Path String, Value Float64, Time UInt32, Date Date, Timestamp UInt32 ) ENGINE = ReplicatedGraphiteMergeTree('/clickhouse/tables/replicator/graphite.data', 'r1', Date, (Path, Time), 8192, 'graphite_rollup')

“graphite.date_metrics” es una tabla rellenada condicionalmente con el motor ReplicatedReplacingMergeTree. Esta tabla contiene los nombres de todas las métricas que se encontraron durante el día. Las razones de la creación se describen en la sección "Problemas" al final de este artículo.

CREATE MATERIALIZED VIEW graphite.date_metrics ( Path String,  Level UInt32,  Date Date) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/replicator/graphite.date_metrics', 'r1', Date, (Level, Path, Date), 8192) AS SELECT toUInt32(length(splitByChar('.', Path))) AS Level, Date, Path FROM graphite.data

“graphite.data_stat” es una tabla condicional con el motor ReplicatedAggregatingMergeTree (replicado AgregandoMergeTree). Esta tabla registra el número de métricas entrantes, divididas en 4 niveles de anidamiento.

CREATE MATERIALIZED VIEW graphite.data_stat ( Date Date,  Prefix String,  Timestamp UInt32,  Count AggregateFunction(count)) ENGINE = ReplicatedAggregatingMergeTree('/clickhouse/tables/replicator/graphite.data_stat', 'r1', Date, (Timestamp, Prefix), 8192) AS SELECT toStartOfMonth(now()) AS Date, replaceRegexpOne(Path, '^([^.]+.[^.]+.[^.]+).*$', '1') AS Prefix, toUInt32(toStartOfMinute(toDateTime(Timestamp))) AS Timestamp, countState() AS Count FROM graphite.data  GROUP BY Timestamp, Prefix

Grafito+ClickHouse. Esquema de interacción de componentes.

Almacenamiento de métricas: cómo pasamos de Graphite+Whisper a Graphite+ClickHouse

Grafito+ClickHouse. Migración de datos

Como recordamos por las expectativas de este proyecto, la transición a ClickHouse debería realizarse sin tiempos de inactividad, por lo que tuvimos que cambiar de alguna manera todo nuestro sistema de monitoreo al nuevo almacenamiento de la manera más transparente posible para nuestros usuarios.
Lo hicimos de esta manera.

  • Se agregó una regla a carbon-c-relay para enviar un flujo adicional de métricas al carbon-clickhouse de uno de los servidores involucrados en la replicación de las tablas de ClickHouse.

  • Escribimos un pequeño script de python que, utilizando la biblioteca de volcado de susurros, leyó todos los archivos .wsp de nuestro almacenamiento y envió estos datos al clickhouse de carbono descrito anteriormente en 24 subprocesos. La cantidad de valores métricos aceptados en carbon-clickhouse alcanzó los 125 millones / min., y ClickHouse ni siquiera sudó.

  • Creamos una fuente de datos separada en Grafana para depurar las funciones utilizadas en los paneles existentes. Reveló una lista de funciones que usamos, pero que no se implementaron en carbonapi. Terminamos estas funciones y enviamos PRs a los autores de carbonapi (gracias especiales a ellos).

  • Para cambiar la carga de lectura en la configuración del balanceador, cambiamos los puntos finales de graphite-api (interfaz API para Graphite+Whisper) a carbonapi.

Grafito+ClickHouse. resultados

  • redujo la utilización del subsistema de disco del 30% al 1%;

    Almacenamiento de métricas: cómo pasamos de Graphite+Whisper a Graphite+ClickHouse

  • redujo la cantidad de espacio ocupado de 1 TB a 300 GB;
  • tenemos la capacidad de recibir 125 millones de métricas por minuto por servidor (picos en el momento de la migración);
  • transfirió todas las métricas a un intervalo de almacenamiento de treinta segundos;
  • replicación de datos recibidos y tolerancia a fallas;
  • conmutado sin tiempo de inactividad;
  • Tomó alrededor de 7 semanas para todo.

Grafito+ClickHouse. Problemas

En nuestro caso, hubo algunas trampas. Esto es lo que encontramos después de la transición.

  1. ClickHouse no siempre vuelve a leer las configuraciones sobre la marcha, a veces necesita recargarse. Por ejemplo, en el caso de la descripción del clúster zookeeper en la configuración de ClickHouse, no se aplicó hasta que se reinició el servidor clickhouse.
  2. No hubo grandes solicitudes de ClickHouse, por lo que en nuestro clickhouse de grafito, la cadena de conexión de ClickHouse se ve así:
    url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000"
  3. ClickHouse lanza con bastante frecuencia nuevas versiones de versiones estables, que pueden contener sorpresas: tenga cuidado.
  4. Los contenedores creados dinámicamente en kubernetes envían una gran cantidad de métricas con una vida útil corta y aleatoria. No hay muchos puntos de acuerdo con tales métricas, y no hay problemas con el lugar. Pero al crear consultas, ClickHouse genera una gran cantidad de estas mismas métricas de la tabla de 'métricas'. En el 90% de los casos, no hay datos para ellos fuera de la ventana (24 horas). Pero el tiempo dedicado a buscar estos datos en la tabla de 'datos' se gasta y, en última instancia, se basa en un tiempo de espera. Para resolver este problema, comenzamos a mantener una vista separada con información sobre las métricas que se encontraron durante el día. Por lo tanto, al crear informes (gráficos) en contenedores creados dinámicamente, sondeamos solo aquellas métricas que se encontraron dentro de la ventana especificada, y no durante todo el tiempo, lo que aceleró enormemente la generación de informes sobre ellas. Para la solución anterior se recolectó clickhouse de grafito (horquilla), que incluye la implementación del trabajo con la tabla date_metrics.

Grafito+ClickHouse. etiquetas

Desde la versión 1.1.0 Graphite se ha hecho oficial etiquetas de soporte. Y estamos pensando activamente en qué y cómo hacer para apoyar esta iniciativa en la pila graphite+clickhouse.

Grafito+ClickHouse. detector de anomalías

Con base en la infraestructura descrita anteriormente, hemos implementado un prototipo de detector de anomalías, ¡y funciona! Pero sobre él, en el próximo artículo.

Suscríbete, presiona la flecha hacia arriba y ¡sé feliz!

Fuente: habr.com

Añadir un comentario