Cómo solucionar cinco problemas de rendimiento y escalado de Elasticsearch

Cómo solucionar cinco problemas de rendimiento y escalado de Elasticsearch

/
Published: February 1, 2017

El diseño de Elasticsearch, igual que el de un coche, está orientado a que los usuarios puedan empezar a utilizarlo de inmediato, sin necesidad de comprender todos los aspectos de su funcionamiento interno. Sin embargo, es solo cuestión de tiempo que se encuentren con algún problema en el motor. En este artículo, analizaremos cinco desafíos habituales de Elasticsearch y le explicaremos cómo enfrentarse a ellos.

Problema n.º 1: El estado del clúster es rojo o amarillo. ¿Qué hago?

es-cluster-status.png

El estado del clúster aparece en rojo si faltan una o varias de las particiones primarias (y sus réplicas) y en amarillo si faltan una o varias de las particiones réplica. Normalmente, esto sucede cuando un nodo se retira del clúster por cualquier motivo (error de hardware, intervalo largo de recolección de elementos no utilizados, etc.). Una vez recuperado el nodo, sus particiones se quedarán en estado de inicialización hasta que vuelvan al estado activo.

El número de particiones en estado de inicialización suele alcanzar su nivel máximo cuando un nodo se vuelve a unir al clúster, y cae de nuevo cuando las particiones pasan al estado activo, como se ve en el siguiente gráfico.

initializing-shards.png

Durante este período de inicialización, el estado del clúster puede pasar de verde a amarillo o rojo hasta que las particiones del nodo en recuperación vuelven al estado activo. En muchos casos, es posible que un breve cambio del estado a amarillo o rojo no requiera ninguna acción por parte del usuario.

es-num-of-nodes.png

Sin embargo, si observa que el estado del clúster se mantiene en rojo o amarillo durante un período de tiempo más extenso, tiene que asegurarse de que el clúster reconozca el número correcto de nodos de Elasticsearch, ya sea consultando el panel de información de Datadog o consultando la API de estado del clúster que analizamos en la segunda parte de esta series.

es-num-of-nodes.png

Que el número de nodos activos sea más bajo de lo esperado indica que al menos uno de los nodos ha perdido su conexión y no ha podido volver a unirse al clúster. Para averiguar qué nodos han dejado el clúster, busque en los registros (ubicados, de manera predeterminada, en la carpeta logs del directorio principal de Elasticsearch) una línea similar a esta:

[TIMESTAMP] ... Cluster health status changed from [GREEN] to [RED]

Las razones de que el nodo haya fallado pueden variar, podría tratarse tanto de errores de hardware o hipervisor como de errores de memoria insuficiente. Compruebe en cualquiera de las herramientas de supervisión aquí descritas si hay algún cambio inusual en las métricas de rendimiento que haya aparecido más o menos a la misma hora a la que ha fallado el nodo, como un súbito repunte en la tasa de solicitudes de búsqueda o indexación. Cuando ya se haya hecho una idea sobre lo que ha pasado, y si se trata de un error temporal, puede tratar de conseguir que los nodos desconectados se recuperen y se vuelvan a unir al clúster. Si se trata de un error permanente y no consigue recuperar el nodo, puede añadir nuevos nodos y dejar que Elasticsearch se encargue de la recuperación desde cualquier partición réplica disponible. Las particiones réplica se pueden convertir en particiones primarias y redistribuirse en los nuevos nodos que se acaban de añadir.

Si ha perdido tanto la copia primaria como la copia réplica de una partición, puede intentar recuperar todos los datos perdidos que sea posible utilizando el módulo de instantáneas y restauración de Elasticsearch. Si no conoce el módulo, tiene que saber que se puede utilizar para almacenar instantáneas de índices a lo largo del tiempo, en un repositorio remoto, a modo de copia de seguridad.

Problema n.º 2: ¡Socorro! Los nodos de datos se están quedando sin espacio en disco

disk-space-available.png

Si todos los nodos de datos se están quedando sin espacio en disco, tendrá que añadir más nodos de datos al clúster. También deberá asegurarse de que los índices tengan suficientes particiones primarias como para equilibrar los datos entre todos los nodos.

Sin embargo, si solo algunos de los nodos se están quedando sin espacio en disco, suele ser síntoma de que se ha inicializado un índice con muy pocas particiones. Si un índice se compone de muy pocas particiones grandes, a Elasticsearch le resulta complicado distribuir dichas particiones entre los nodos de manera equilibrada.

Elasticsearch tiene en cuenta el espacio en disco disponible cuando asigna las particiones a los nodos. De forma predeterminada, no asignará particiones a los nodos con más del 85 % del disco en uso. En Datadog, puede configurar una alerta de umbral que le envíe una notificación cuando el uso del espacio en disco de cualquiera de los nodos de datos se aproxime al 80 %, lo que le dará el tiempo suficiente para actuar. Cuando queda poco espacio en disco, hay dos soluciones posibles. Una pasa por eliminar los datos obsoletos y almacenarlos fuera del clúster. Puede que no sea una opción viable para todos los usuarios, pero, si almacena datos basados en el tiempo, puede almacenar fuera del clúster una instantánea de los datos de índices más antiguos a modo de copia de seguridad y actualizar la configuración de los índices para desactivar la réplica de dichos índices.

La segunda solución es la única posible si lo que quiere es continuar almacenando todos sus datos en el clúster: el escalado horizontal o vertical. Si opta por un escalado vertical, tendrá que actualizar el hardware. Sin embargo, para evitar tener que volver a actualizar más adelante, debería sacar partido del hecho de que el diseño de Elasticsearch esté orientado al escalado horizontal. Para adaptarse mejor al futuro crecimiento, vuelva a indexar los datos e indique más particiones primarias en el índice que se acaba de crear (asegúrese de tener los nodos suficientes como para distribuir las particiones equitativamente).

Otra forma de realizar un escalado horizontal pasa por sustituir el índice creando un nuevo índice y utilizando un alias para unir ambos índices bajo un mismo espacio de nombres. Si bien, técnicamente, no existe un límite a la cantidad de datos que se puede almacenar en una única partición, Elasticsearch recomienda una capacidad máxima de 50 GB por partición, que se puede utilizar como indicador general de la necesidad de iniciar un nuevo índice.

Problema n.º 3: Las búsquedas tardan demasiado en ejecutarse

El rendimiento de las búsquedas varía mucho en función del tipo de datos que se están buscando y de cómo se estructura cada consulta. Según la organización de los datos, es posible que tenga que probar distintos métodos para encontrar el que le permita agilizar el rendimiento de las búsquedas. En este artículo, nos ocuparemos de dos de ellos: enrutamiento personalizado y combinación forzada.

Normalmente, cuando un nodo recibe una solicitud de búsqueda, tiene que comunicar dicha solicitud a una copia (ya sea primaria o réplica) de cada partición del índice. El enrutamiento personalizado le permite almacenar datos relacionados en la misma partición, de manera que solo tenga que ejecutar la búsqueda en una única partición para satisfacer una consulta. Por ejemplo, puede almacenar todos los datos de blogger1 en la misma partición especificando un valor _routing en la asignación del tipo blogger en su índice, blog_index.

En primer lugar, asegúrese de que _routing sea obligatorio para no olvidarse de especificar un valor de enrutamiento personalizado siempre que indexe información de tipo blogger.

curl -XPUT "localhost:9200/blog_index" -d '
{
  "mappings": {
    "blogger": {
      "_routing": {
        "required": true 
      }
    }
  }
}'

Cuando esté preparado para indexar un documento perteneciente a blogger1, especifique el valor de enrutamiento:

curl -XPUT "localhost:9200/blog_index/blogger/1?routing=blogger1" -d '
{
  "comment": "blogger1 made this cool comment"
}'

Para realizar una búsqueda en los comentarios de blogger1, deberá recordar especificar el valor de enrutamiento en la consulta, como se muestra a continuación:

curl -XGET "localhost:9200/blog_index/_search?routing=blogger1" -d '
{
  "query": {
    "match": {
      "comment": {
        "query": "cool comment"
      }
    }
  }
}'

En Elasticsearch, cada solicitud de búsqueda tiene que comprobar cada uno de los segmentos de cada una de las particiones donde encuentre una coincidencia. Así pues, una vez que haya reducido el número de particiones en las que se vaya a ejecutar la búsqueda, puede reducir también el número de segmentos por partición desencadenando la API de combinación forzada en uno o varios de los índices. La API de combinación forzada (o API de optimización, en versiones anteriores a la 2.1.0) hace que los segmentos del índice sigan combinándose hasta que el recuento de segmentos de cada partición se reduzca a max_num_segments (1, de forma predeterminada). Vale la pena probar esta función, pero tenga en cuenta el coste computacional de desencadenar un número elevado de combinaciones.

Por lo que se refiere a particiones con un gran número de segmentos, el proceso de combinación forzada supone un gasto mucho mayor de recursos informáticos. Por ejemplo, la combinación forzada de un índice de 10.000 segmentos para conseguir 5.000 segmentos no supone mucho tiempo, pero combinar 10.000 segmentos hasta llegar a solo uno puede llevar horas. Cuanta más combinación sea necesaria, más recursos se retirarán de la ejecución de solicitudes de búsqueda, lo que sería contrario al propósito de invocar una combinación forzada. En cualquier caso, se recomienda programar la combinación forzada fuera de las horas de mayor actividad, como durante la noche, cuando no se esperen muchas solicitudes de búsqueda o indexación.

Problema n.º 4: ¿Cómo puedo agilizar las cargas de trabajo que utilizan muchos índices?

Elasticsearch se suministra preconfigurado con muchos valores que tratan de garantizar que se conserven los suficientes recursos como para buscar e indexar datos. Sin embargo, si el uso que va a dar a Elasticsearch está muy orientado a la escritura, quizás le convenga adaptar algunos valores para potenciar el rendimiento de la indexación, aunque ello implique perder rendimiento de búsqueda o réplica de datos. A continuación, analizaremos distintos métodos para optimizar casos prácticos de indexación, no de búsqueda, de datos.

  • Asignar particiones: Como estrategia de alto nivel, si va a crear un índice que vaya a actualizar con frecuencia, asegúrese de designar las suficientes particiones primarias como para poder distribuir la carga de indexación equitativamente entre todos los nodos. Habitualmente, se recomienda asignar una partición primaria por nodo del clúster, y posiblemente dos o más particiones primarias por nodo, pero solo si dispone de mucho ancho de banda de disco o potencia de CPU en dichos nodos. Recuerde, de todas maneras, que la sobreasignación de particiones añade sobrecarga y puede afectar negativamente a las búsquedas, dado que las solicitudes de búsqueda necesitan alcanzar todas las particiones del índice. Por otro lado, si asigna un número de particiones primarias inferior al número de nodos, podría crear zonas activas, ya que los nodos que contengan dichas particiones tendrán que gestionar más solicitudes de indexación que los nodos que no contengan particiones de índice.

  • Inhabilitar la limitación de combinaciones: La limitación de combinaciones es la tendencia automática de Elasticsearch a limitar las solicitudes de indexación cuando detecta que la combinación se está quedando rezagada con respecto a la indexación. Es lógico actualizar los valores del clúster para inhabilitar la limitación de combinaciones (para ello, establezca indices.store.throttle.type en “none”) cuando se pretende optimizar el rendimiento de la indexación, no de la búsqueda. Puede hacer que este cambio sea persistente (lo que quiere decir que se mantendrá tras el reinicio del clúster) o transitorio (volverá al valor predeterminado en caso de reinicio), en función de cada caso práctico.

  • Incrementar el tamaño del búfer de indexación : Este valor (indices.memory.index_buffer_size) determina hasta qué punto se puede llenar el búfer antes de que sus documentos se graben en un segmento del disco. El valor predeterminado limita este valor al 10 % del montón total para reservar la mayor parte del montón al servicio de las solicitudes de búsqueda, lo que no resulta útil si Elasticsearch se utiliza sobre todo para la indexación.

  • Ejecutar la indexación primero y luego la réplica: Cuando inicialice un índice, especifique cero particiones réplica en la configuración del índice y añada las réplicas cuando haya finalizado la indexación. Esto potenciará el rendimiento de la indexación, pero puede resultar un poco arriesgado si el nodo que contiene la única copia de los datos se bloquea antes de poder replicarlo.

  • Reducir la frecuencia de actualización: Aumente el intervalo de actualización en la API de configuración del índice. De forma predeterminada, el proceso de actualización de índices se genera cada segundo, pero, en caso de periodos con una elevada carga de indexación, reducir la frecuencia de actualización puede ayudar a aliviar, en parte, la carga de trabajo.

  • Corregir la configuración del registro de transacciones: A partir de la versión 2.0, Elasticsearch vaciará los datos del registro de transacciones en disco tras cada solicitud, lo que reduce el riesgo de que se pierdan datos en caso de error del hardware. Si quiere dar prioridad al rendimiento de la indexación con respecto a una potencial pérdida de datos, puede cambiar el valor index.translog.durability a async en la configuración del índice. De este modo, el índice solo escribirá en el disco en intervalos marcados por el valor sync_interval, no tras cada solicitud, con lo que habrá más recursos libres para atender a las solicitudes de indexación.

Si quiere ver más sugerencias sobre cómo potenciar el rendimiento de la indexación, consulte este manual de Elastic.

Problema n.º 5: ¿Qué puedo hacer con los rechazos masivos del grupo de subprocesos?

bulk-rejections-top.png

Los rechazos del grupo de subprocesos suelen indicar que se están enviando demasiadas solicitudes a los nodos, con demasiada rapidez. Si se trata de algo temporal (por ejemplo, si tiene que indexar una cantidad excepcionalmente grande de datos esta semana, pero prevé que pronto volverá a la normalidad), puede intentar ralentizar el ritmo de las solicitudes. Sin embargo, si quiere que el clúster pueda mantener el ritmo de solicitudes actual, es posible que necesite escalar el clúster añadiendo más nodos de datos. Para utilizar la potencia de procesamiento del mayor número de nodos, debería asegurarse también de que los índices contengan las suficientes particiones como para poder distribuir equitativamente la carga entre todos los nodos.

¡Optimice su entorno para seguir avanzando!

Encontrará más sugerencias sobre el rendimiento en los recursos de formación y la documentación de Elasticsearch. Dado que los resultados variarán en función de cada caso práctico y cada configuración, puede probar distintas configuraciones y estrategias de indexación o consulta para averiguar cuál es la mejor opción para sus clústeres.

Cuando experimente con estas y otras sugerencias de optimización, asegúrese de observar detenidamente los paneles de información de Elasticsearch, a fin de supervisar el impacto que pueda causar sobre las métricas de rendimiento clave de los clústeres.

Con un panel de información integrado de Elasticsearch que destaca las principales métricas del clúster, Datadog le permite supervisar eficazmente Elasticsearch en tiempo real. Si ya tiene una cuenta de Datadog, puede configurar la integración de Elasticsearch en cuestión de minutos. Si todavía no tiene una cuenta de Datadog, regístrese y obtenga una hoy mismo.

Este articulo ha sido traducido. La version original se encuentra aquí con el resto de la series, en ingles.