Elasticsearch en producción: mejores prácticas de implementación

Elasticsearch es un motor de búsqueda altamente optimizado para análisis de datos modernos.

Elasticsearch es un sorprendente motor de búsqueda y análisis en tiempo real. Está construido sobre Apache Lucene. Está distribuido, RESTful, fácil de comenzar a usar y altamente disponible. Los casos de uso de Elasticsearch incluyen potenciar la búsqueda, monitoreo de transacciones y detección de errores, descubrimiento de contenido, análisis de registros, búsqueda difusa, agregación de datos de eventos, visualización de datos. Elasticsearch y el resto de Elastic Stack han demostrado ser extremadamente versátiles, y como puede ver en los casos de uso anteriores, hay varias formas de integrar Elasticsearch en lo que su producto ofrece hoy y agregarle información adicional.

Lo utilizamos mucho para búsqueda y análisis en Botmetric, indexamos alrededor de mil millones de documentos al día y utilizamos agregaciones muy complejas para la visualización de datos en tiempo real.

Dicho esto, el arranque de una aplicación frente a su ejecución en producción y mantenimiento es totalmente diferente. Este artículo cubre muchos de estos factores de las experiencias de la vida real y son los elementos comunes básicos que debe considerar para ejecutar Elasticsearch en producción.

Memoria:

Elasticsearch y Lucene están escritos en Java, lo que significa que debe tener en cuenta las estadísticas de JVM y el espacio dinámico. Cuanto más almacenamiento dinámico esté disponible para Elasticsearch, más memoria puede usar para el filtro y el almacenamiento en caché para aumentar el rendimiento de las consultas. Pero tenga en cuenta que demasiado montón puede someterlo a largas pausas de recolección de basura. No establezca Xmx por encima del límite que utiliza la JVM para punteros de objetos comprimidos (ups comprimidos); el límite exacto varía pero está cerca de 32 GB.

Un problema común es configurar un montón que es demasiado grande. Tiene una máquina de 64 GB y, por cierto, quiere darle a Elasticsearch los 64 GB de memoria. ¡Más es mejor! El montón es definitivamente importante para Elasticsearch. Es utilizado por muchas estructuras de datos en memoria para proporcionar una operación rápida. Pero dicho esto, hay otro usuario importante de memoria que está fuera del montón: el caché de archivos del sistema operativo.

Lucene está diseñado para aprovechar el sistema operativo subyacente para almacenar en caché las estructuras de datos en memoria. Los segmentos de Lucene se almacenan en archivos individuales. Como los segmentos son inmutables, estos archivos nunca cambian. Esto los hace muy amigables con la caché, y el sistema operativo subyacente mantendrá felices los segmentos calientes residentes en la memoria para un acceso más rápido. Estos segmentos incluyen tanto el índice invertido (para búsqueda de texto completo) como los valores doc (para agregaciones). El rendimiento de Lucene se basa en esta interacción con el sistema operativo. Pero si le da toda la memoria disponible al montón de Elasticsearch, no quedará nada para el caché de archivos del sistema operativo. Esto puede afectar seriamente el rendimiento. La recomendación estándar es dar el 50% de la memoria disponible al montón de Elasticsearch, mientras se deja el otro 50% libre. No quedará sin usar; Lucene felizmente consumirá lo que quede para el caché de archivos. El almacenamiento dinámico de Elasticsearch se puede configurar de la siguiente manera,

exportar ES_HEAP_SIZE = 10g

o

ES_JAVA_OPTS = "- Xms10g -Xmx10g" ./bin/elasticsearch

UPC:

Elasticsearch admite agregaciones y consultas filtradas. La ejecución de consultas filtradas complejas, la indexación intensiva, la filtración y las consultas contra índices necesitan una gran cantidad de CPU, por lo que elegir la correcta es fundamental. Uno debe comprender las especificaciones de la CPU y cómo se comportan con Java a medida que las consultas se ejecutan en JVM.

Cada grupo ejecuta una serie de subprocesos, que se pueden configurar, y tiene una cola. No se recomienda cambiar esto a menos que tenga un requisito muy específico, ya que Elasticsearch realiza la asignación de núcleos dinámicamente.

Tipos de grupo de subprocesos:

Elasticsearch tiene 3 tipos de grupos de subprocesos.

  1. En caché: el grupo de subprocesos en caché es un grupo de subprocesos ilimitados que generará un subproceso si hay solicitudes pendientes. Este grupo de subprocesos se utiliza para evitar que las solicitudes enviadas a este grupo se bloqueen o sean rechazadas. Los subprocesos no utilizados en este grupo de subprocesos se finalizarán después de que caduque un mantenimiento activo (el valor predeterminado es cinco minutos). El grupo de subprocesos en caché está reservado para el grupo de subprocesos genérico.
  2. Corregido: el grupo de subprocesos fijos tiene un tamaño fijo de subprocesos para manejar las solicitudes con una cola (opcionalmente limitada) para solicitudes pendientes que no tienen subprocesos para atenderlos. El parámetro de tamaño controla el número de subprocesos y el valor predeterminado es el número de núcleos multiplicado por 5.
  3. Escalado: el grupo de subprocesos de escala contiene un número dinámico de subprocesos. Este número es proporcional a la carga de trabajo y varía entre 1 y el valor del parámetro de tamaño.

Elasticsearch divide el uso de la CPU en grupos de subprocesos de varios tipos:

  • genérico: para operaciones estándar como el descubrimiento y el tipo de grupo de subprocesos se almacena en caché.
  • index: para operaciones de indexado / borrado. El tipo de grupo de subprocesos es fijo.
  • búsqueda: para operaciones de conteo / búsqueda. El tipo de grupo de subprocesos es fijo.
  • get: para obtener operaciones. El tipo de grupo de subprocesos es fijo.
  • bulk: para operaciones masivas como la indexación masiva. El tipo de grupo de subprocesos es fijo. La mejor configuración de los documentos en masa depende de la configuración del clúster, esto se puede identificar probando varios valores.
  • percolate: para percolación. El tipo de grupo de subprocesos es fijo.
  • actualizar: para operaciones de actualización. El tipo de grupo de subprocesos está escalando.

Se puede cambiar un grupo de subprocesos específico estableciendo sus parámetros específicos de tipo.

Leer más https://www.elastic.co/guide/en/elasticsearch/reference/2.2/modules-threadpool.html#types

Tamaño del fragmento:

El fragmento es la unidad en la que Elasticsearch distribuye datos dentro del clúster. La velocidad a la que Elasticsearch puede mover fragmentos al reequilibrar los datos, p. después de una falla, dependerá del tamaño y la cantidad de fragmentos, así como del rendimiento de la red y el disco.

En Elasticsearch, cada consulta se ejecuta en un solo hilo por fragmento. Sin embargo, se pueden procesar múltiples fragmentos en paralelo, al igual que múltiples consultas y agregaciones contra el mismo fragmento.

Esto significa que la latencia mínima de la consulta, cuando no hay almacenamiento en caché, dependerá de los datos, el tipo de consulta y el tamaño del fragmento. La consulta de muchos fragmentos pequeños hará que el procesamiento por fragmento sea más rápido, pero dado que se deben poner en cola y procesar muchas más tareas en secuencia, no necesariamente será más rápido que consultar un número menor de fragmentos más grandes. Tener muchos fragmentos pequeños también puede reducir el rendimiento de la consulta si hay múltiples consultas concurrentes.

Cada fragmento tiene datos que deben mantenerse en la memoria y utiliza espacio de almacenamiento dinámico. Esto incluye estructuras de datos que contienen información a nivel de fragmento y también a nivel de segmento para definir dónde residen los datos en el disco. El tamaño de estas estructuras de datos no es fijo y variará según el caso de uso. Sin embargo, una característica importante de la sobrecarga relacionada con el segmento es que no es estrictamente proporcional al tamaño del segmento. Esto significa que los segmentos más grandes tienen menos sobrecarga por volumen de datos en comparación con los segmentos más pequeños. La diferencia puede ser sustancial. Elegir la cantidad correcta de fragmentos es complicado porque nunca se sabe cuántos documentos obtendrá antes de comenzar. Tener muchos fragmentos puede ser bueno y terrible para un grupo. La gestión de índices y fragmentos puede sobrecargar el nodo maestro, lo que puede dejar de responder y provocar un comportamiento extraño y desagradable. Asigne a sus nodos maestros suficientes recursos para hacer frente al tamaño del clúster.

Lo malo es que la cantidad de fragmentos es inmutable y se define cuando se crea el índice. Una vez que se crea el índice, la única forma de cambiar el número de fragmentos es eliminar sus índices, crearlos nuevamente y volver a indexar.

Replicación

Elasticsearch admite la replicación, los datos se replican entre los nodos de datos para que una pérdida de nodo no conduzca a la pérdida de datos. Por defecto, el factor de replicación es 1, pero dependiendo de los requisitos de su producto se puede aumentar. Cuantas más réplicas, más resistentes a desastres serán sus datos. Otra ventaja de tener más réplicas es que cada nodo contiene un fragmento de réplica, lo que mejora el rendimiento de la consulta ya que las réplicas también se utilizan para realizar consultas.

La fórmula de replicación utilizada por Elasticsearch para lograr consistencia es,

(primario + número_de_replicas) / 2 + 1

Optimizando la asignación

Según los requisitos de datos del producto, podemos clasificar los datos en frío y calor. A los índices a los que se accede con más frecuencia que a otros, se les pueden asignar más nodos de datos, mientras que los índices a los que se accede con menos frecuencia pueden tener menos recursos asignados. Esta estrategia es especialmente útil para almacenar datos de series temporales como registros de aplicaciones (por ejemplo: ELK).

Esto se puede lograr ejecutando un cronjob que mueva los índices a diferentes nodos a intervalos regulares.

El nodo activo es un tipo de nodo de datos que realiza toda la indexación dentro del clúster. También contienen los índices más recientes, ya que estos generalmente tienden a consultarse con mayor frecuencia. Como la indexación es una operación intensiva de CPU e IO, estos servidores deben ser potentes y respaldados por el almacenamiento SSD adjunto. Recomendamos ejecutar un mínimo de 3 nodos activos para una alta disponibilidad. Sin embargo, dependiendo de la cantidad de datos recientes que desee recopilar y consultar, es posible que necesite aumentar este número para lograr sus objetivos de rendimiento.

El nodo cálido es un tipo de nodo de datos diseñado para manejar una gran cantidad de índices de solo lectura que no es tan probable que se consulten con frecuencia. Como estos índices son de solo lectura, los nodos calientes tienden a utilizar discos grandes adjuntos (generalmente discos giratorios) en lugar de SSD. Al igual que con el nodo en caliente, recomendamos un mínimo de 3 nodos en caliente para una alta disponibilidad. Y como antes, con la advertencia de que grandes cantidades de datos pueden requerir nodos adicionales para cumplir con los requisitos de rendimiento. También tenga en cuenta que las configuraciones de CPU y memoria a menudo necesitarán reflejar las de sus nodos activos. Esto solo puede determinarse probando con consultas similares a las que experimentaría en una situación de producción.

Para obtener más detalles sobre el nodo caliente y cálido, consulte aquí.

Otra estrategia que puede adaptar es archivar los índices en s3 y restaurar cuando necesite datos de esos índices. Puedes leer más sobre esto desde aquí.

Topología de nodo:

Los nodos de Elasticsearch se pueden dividir en tres categorías: nodo maestro, nodo de datos, nodo de cliente.

  1. Nodo maestro: el nodo maestro puede ser pequeño si no es también un nodo de datos, ya que no almacena ningún índice / fragmento. Su responsabilidad es almacenar el estado detallado del clúster y ayudar a los datos y otros nodos en la búsqueda de metadatos de índices / fragmentos. Elasticsearch debe tener múltiples nodos maestros para evitar problemas cerebrales divididos.
  2. Nodo de datos: el nodo de datos es responsable de almacenar / consultar los datos del índice real.
  3. Nodo cliente: el nodo cliente se utiliza como proxy para indexar y buscar. Esto es muy recomendable si las agregaciones se usan mucho. Estos son nodos especiales de ElasticSearch que no son elegibles para datos o maestros. Los nodos del cliente son conscientes del clúster y, por lo tanto, pueden actuar como equilibradores de carga inteligentes. Puede enviar sus consultas a los nodos del cliente que luego pueden asumir la costosa tarea de recopilar respuestas a los resultados de la consulta de cada uno de los nodos de datos.

agregue esta configuración al archivo elasticsearch.yml para los nodos respectivos.

Nodo maestro: node.master: true node.data:false
Nodo de datos: node.master: false node.data:true
Nodo cliente: node.master: false node.data:false

Consejos para solucionar problemas:

El rendimiento de Elasticsearch depende en gran medida de la máquina en la que está instalado. CPU, uso de memoria y E / S de disco son métricas básicas del sistema operativo para cada nodo Elasticsearch. Se recomienda que mire las métricas de la máquina virtual Java (JVM) cuando aumente el uso de la CPU. En el siguiente ejemplo, la razón del aumento fue una mayor actividad de recolección de basura.

  1. Presión de almacenamiento dinámico: la presión de memoria alta funciona contra el rendimiento del clúster de dos maneras: a medida que la presión de la memoria aumenta al 75% y más, queda menos memoria disponible, y su clúster ahora también necesita gastar algunos recursos de la CPU para recuperar la memoria a través de la recolección de basura. Estos ciclos de CPU no están disponibles para manejar las solicitudes de los usuarios mientras la recolección de basura está activada. Como resultado, los tiempos de respuesta para las solicitudes de los usuarios aumentan a medida que el sistema se vuelve cada vez más limitado de recursos. Si la presión de memoria continúa aumentando y alcanza cerca del 100%, se usa una forma mucho más agresiva de recolección de basura, que a su vez afectará drásticamente los tiempos de respuesta del clúster. La métrica de Índice de tiempos de respuesta muestra que la alta presión de memoria conduce a un impacto significativo en el rendimiento.
  2. Crecimiento en la memoria sin almacenamiento dinámico de la JVM, eliminando la memoria destinada a la memoria caché de la página y posiblemente causando la cosecha de OOM a nivel de núcleo
  3. Evita problemas de cerebro dividido. El cerebro dividido es un escenario en el que el clúster se divide. Por ejemplo, tiene un clúster de 6 nodos. 2 nodos se desconectan del clúster, pero aún pueden verse. Estos 2 nodos luego crean otro clúster. Incluso elegirán un nuevo maestro entre ellos. Ahora tenemos dos grupos con el mismo nombre, uno con 4 nodos y otro con 2 nodos. Cada uno tiene un nodo maestro también. Esto es lo que se denomina problema de cerebro dividido con clústeres ES. Para evitar esto, configure el parámetro ES discovery.zen.minimum_master_nodes en la mitad del número de nodos + 1.
  4. Dado que Elasticsearch usa mucho los dispositivos de almacenamiento, el monitoreo de la E / S del disco asegura que esta necesidad básica se cumpla. Hay muchas razones para reducir la E / S de disco, se considera una métrica clave para predecir muchos tipos de problemas. Es una buena métrica verificar la efectividad de la indexación y el rendimiento de las consultas. El análisis de las operaciones de lectura y escritura indica directamente qué es lo que más necesita el sistema en el caso de uso específico. La configuración del sistema operativo para la E / S del disco es una base para todas las demás optimizaciones, sintonizar la E / S del disco puede evitar posibles problemas. Si la E / S del disco aún no es suficiente, se deben evaluar las contramedidas, como la optimización de la cantidad de fragmentos y su tamaño, la aceleración de las fusiones, la sustitución de discos lentos, el cambio a SSD o la adición de más nodos de acuerdo con las circunstancias que causan la E / S cuellos de botella
  5. Para las aplicaciones que dependen de la búsqueda, la experiencia del usuario está altamente correlacionada con la latencia de las solicitudes de búsqueda. Hay muchas cosas que pueden afectar el rendimiento de la consulta, como consultas construidas, clúster Elasticsearch configurado incorrectamente, memoria JVM y problemas de recolección de basura, disco IO, etc. La latencia de consulta es la métrica que afecta directamente a los usuarios, así que asegúrese de ponerle algunas alertas.
  6. La mayoría de los filtros en Elasticsearch se almacenan en caché de forma predeterminada. Eso significa que durante la primera ejecución de una consulta filtrada, Elasticsearch encontrará documentos que coincidan con el filtro y creará una estructura llamada "bitset" utilizando esa información. Los datos almacenados en el conjunto de bits contienen un identificador de documento y si un documento dado coincide con el filtro. Las ejecuciones posteriores de consultas que tengan el mismo filtro reutilizarán la información almacenada en el conjunto de bits, acelerando así la ejecución de consultas al guardar las operaciones de E / S y los ciclos de CPU. Se recomienda usar el filtro en la consulta. Para más detalles consulte aquí.
  7. El tiempo de actualización y el tiempo de fusión están estrechamente relacionados con el rendimiento de indexación, además de que afectan el rendimiento general del clúster. El tiempo de actualización aumenta con el número de operaciones de archivo para el índice Lucene (fragmento).
  8. Habilitar el registro lento de consultas ayudará a identificar qué consultas son lentas y qué se puede hacer para mejorarlas, especialmente útil para consultas comodín.
  9. Aumente el tamaño de ulimit para permitir archivos máximos.
  10. El rendimiento de ElasticSearch puede verse afectado cuando el sistema operativo decide cambiar la memoria de la aplicación no utilizada. Deshabilite el intercambio configurando la configuración del nivel del sistema operativo o establezca lo siguiente en ElasticSearch config bootstrap.mlockall: true
  11. Inhabilite la eliminación de todos los índices por consulta comodín. Para asegurarse de que alguien no emita una operación DELETE en todos los índices (* o _todos) establezca action.destructive_requires_name en true.

Antes de terminar, aquí está la lista de URL que son útiles para ver las métricas.

  • / _cluster / health? pretty: para el indicador de salud del clúster.
  • / _status? pretty: para toda la información sobre todos los índices.
  • / _nodes? pretty: para toda la información sobre los nodos.
  • / _cat / master? pretty: para el nodo maestro.
  • / _stats? pretty: para la asignación de fragmentos, estadísticas de índices.
  • / _nodes / stats? pretty: para las estadísticas de nodos individuales, esto incluye, jvm, http, io stats para el nodo.

La agregación de métricas de Elasticsearch es compatible con la mayoría de las herramientas de monitoreo del sistema como Datadog, TICK. Se recomienda el uso de tales herramientas y se recomienda crear un embudo para el monitoreo continuo de Elasticsearch.

Conclusión:

Elasticsearch es un motor de análisis y búsqueda de texto completo distribuido, que permite a múltiples inquilinos buscar a través de sus conjuntos de datos completos, independientemente de su tamaño, a velocidades sin precedentes. Además de sus capacidades de búsqueda de texto completo, ElasticSearch también funciona como un sistema de análisis y una base de datos distribuida. ElasticSearch tiene excelentes valores predeterminados para comenzar. Pero una vez pasada la etapa de experimentación inicial, debe dedicar un tiempo a ajustar la configuración según sus necesidades. Se recomienda que vuelva a visitar su configuración más adelante, junto con la documentación oficial, para asegurarse de que su clúster esté configurado para satisfacer sus necesidades.