18 September 2017

¿Cuántos shards debo tener en mi cluster de Elasticsearch?

By Christian Dahlqvist

Elasticsearch es una plataforma muy versátil que admite una gran variedad de casos de uso y ofrece gran flexibilidad en torno a la organización de datos y las estrategias de replicación. No obstante, esta flexibilidad a veces puede hacer que sea difícil determinar de antemano cómo organizar mejor sus datos en índices y shards, especialmente si Elastic Stack es nuevo para usted. Si bien las demás alternativas no necesariamente generarán problemas al inicio, es probable que creen problemas de rendimiento a medida que el volumen de datos crezca con el tiempo. Mientras más datos contenga el cluster, más difícil será corregir el problema, ya que es posible que se necesite reindexar grandes cantidades de datos.

Cuando acuden a nosotros usuarios con problemas de rendimiento, con frecuencia el origen de estos radica en cómo se indexan los datos y la cantidad de shards en el cluster. Esto es especialmente cierto cuando hay casos de uso con tenencias múltiples o índices temporales. Cuando analizamos esto con los usuarios, en persona en eventos o reuniones o a través de nuestro foro, algunas de las preguntas más comunes que escuchamos son «¿Cuántos shards debería tener?» y «¿Qué tan grandes deben ser los shards?».

Este artículo del blog tiene como objetivo responder estas preguntas y ofrecer pautas prácticas para los casos de uso con índices temporales, por ejemplo, registros o análisis de seguridad, todo en un mismo lugar.

¿Qué es un shard?

Antes de comenzar, debemos establecer algunos datos y términos que necesitaremos más adelante.

En Elasticsearch, los datos se organizan en índices. Cada índice está compuesto por uno o más shards. Cada shard es una instancia de un índice de Lucene, que podría imaginarse como un motor de búsqueda en sí mismo, que indexa y administra consultas para un subconjunto de datos en un cluster de Elasticsearch.

A medida que se escriben datos en un shard, estos se publican en nuevos segmentos inmutables de Lucene en el disco, y es entonces que están disponibles para consultas. Esto se denomina «update». Encontrará más detalles sobre cómo funciona esto en Elasticsearch: La guía definitiva.

A medida que la cantidad de segmentos aumenta, estos se consolidan en segmentos más grandes de forma periódica. Este proceso se conoce como merge. Todos los segmentos son inmutables. Esto significa que el espacio de disco utilizado, generalmente, fluctuará durante la indexación, ya que es necesario crear nuevos segmentos combinados antes de poder eliminar los segmentos que reemplazan. La combinación puede insumir muchos recursos, especialmente del disco de E/S.

Shard es la unidad en la que Elasticsearch distribuye datos en el cluster. La velocidad a la que Elasticsearch puede mover shards cuando se balancean datos, por ejemplo, tras un fallo, depende del tamaño y la cantidad de shards, además del rendimiento de la red y el disco.

CONSEJO: Evite los shards muy grandes, ya que pueden tener un impacto negativo en la capacidad del cluster de recuperarse tras un fallo. No hay un límite fijo respecto del tamaño de los shards, pero se considera que los shards de 50 GB funcionan con una gran variedad de casos de uso.

Indexación por período de retención

Dado que los segmentos son inmutables, actualizar un documento exige que Elasticsearch primero encuentre el documento actual, luego lo marque como «eliminado» y agregue la versión actualizada. Eliminar un documento también exige que, antes, se encuentre el documento y se marque como «eliminado». Por esta razón, los documentos eliminados seguirán ocupando espacio del disco y usando recursos del sistema hasta que desaparezcan.

Elasticsearch permite eliminar índices completos de forma eficaz, directamente desde el sistema de archivos, sin tener que borrar los registros uno por uno. Esta es, sin duda, la forma más eficaz de eliminar datos de Elasticsearch.


CONSEJO: Intente usar índices temporales para administrar la retención de datos siempre que sea posible. Agrupe los datos en índices basados en períodos de retención. Los índices temporales también facilitan la variación de la cantidad de shards primarios y réplicas con el tiempo, ya que esto puede modificarse para el siguiente índice que se generará. Esto hace que sea más fácil adaptarse a los volúmenes de datos y requisitos en forma dinámica.


¿Los índices y los shards no son gratuitos?

Para cada índice de Elasticsearch, la información sobre mapeos y estados se almacena en el estado del cluster. Esto se conserva en la memoria para que sea de rápido acceso. Por lo tanto, tener una gran cantidad de índices en un cluster puede hacer que el estado del cluster sea grande, especialmente si los mapeos son de gran tamaño. Esto puede ocasionar actualizaciones lentas, ya que todas las actualizaciones tienen que hacerse mediante un único hilo para garantizar la consistencia antes de que los cambios se distribuyan en todo el cluster.


CONSEJO: A fin de reducir la cantidad de índices y evitar mapeos de gran tamaño y mutables en el tiempo, considere almacenar los datos con una estructura similar en el mismo índice, en lugar de dividirlos en índices independientes basados en el origen de los datos. Es importante encontrar el equilibrio adecuado entre la cantidad de índices y el tamaño de shard para cada índice individual.


Cada shard contiene datos que deben conservarse en la memoria y que ocupan espacio del heap. Esto incluye estructuras de datos que contienen información al nivel del shard, pero también a nivel del segmento, a fin de definir en qué parte del disco residen los datos. 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 segmentos es que no es estrictamente proporcional al tamaño de los segmentos. Esto significa que los segmentos más grandes implican menor sobrecarga por volumen de datos, en comparación con los segmentos más pequeños. La diferencia puede ser sustancial.

Para poder almacenar la mayor cantidad de datos posible por nodo, es importante administrar el uso del heap y reducir la cantidad de sobrecarga en la mayor medida que se pueda. Mientras más espacio del heap tenga un nodo, más datos y shards podrá admitir.

Por lo tanto, los índices y los shards no son gratuitos desde el punto de vista del cluster, ya que existe determinado nivel de sobrecarga de recursos para cada uno.


CONSEJO: Los shards pequeños generan segmentos pequeños, lo que aumenta la sobrecarga. Intente mantener un tamaño de shard promedio, entre unos pocos GB y algunas decenas de GB. Para los casos de uso con datos temporales, es común ver shards de entre 20 GB y 40 GB de tamaño.

CONSEJO: Dado que la sobrecarga por shard depende de la cantidad y el tamaño de los segmentos, si fuerza a los segmentos más pequeños a combinarse para formar segmentos más grandes mediante una operación de forcemerge, puede reducir la sobrecarga y optimizar el rendimiento de las consultas. Lo ideal es hacer esto una vez que no se escriban más datos en el índice. Tenga en cuenta que esta operación es costosa y que debe llevarse a cabo durante horas que no sean pico.

CONSEJO: La cantidad de shards que puede contener un nodo será proporcional a la cantidad de heap disponible, pero Elasticsearch no impone límites fijos. La regla de oro es asegurarse de mantener la cantidad de shards por nodo por debajo de 20 a 25 por GB de heap configurado. Por lo tanto, un nodo con un heap de 30 GB debe contar con un máximo de 600 a 750 shards, pero será incluso mejor mantener las cifras por debajo de este límite. Generalmente, esto permitirá que el cluster se mantenga sin fallos.


¿Cómo afecta el rendimiento el tamaño de los shards?

En Elasticsearch, las consultas se ejecutan en un único hilo por shard. No obstante, pueden procesarse múltiples shards en paralelo, al igual que pueden procesarse múltiples consultas y agregaciones en relación con el mismo shard.

Esto significa que, siempre que no haya almacenamiento en caché involucrado, la latencia de consulta mínima dependerá de los datos, el tipo de consulta y el tamaño del shard. Consultar múltiples shards pequeños hará que el hilo por shard sea más rápido, pero, dado que más tareas tendrán que ponerse en cola y procesarse en secuencia, no necesariamente será más rápido que consultar una cantidad de shards más pequeña de mayor tamaño por shard. Al contar con diversos shards pequeños, también podrá reducir la capacidad de consultas si hay varias consultas en simultáneo.


CONSEJO: La mejor forma de determinar el tamaño máximo de los shards desde el punto de vista del rendimiento de las consultas es crear una prueba representativa mediante datos y consultas realistas. Siempre tome como parámetro una consulta y una carga de escritura que representen lo que necesitaría el nodo para administrar la carga en producción, ya que la optimización para una única consulta podría generar resultados engañosos.


¿Cómo administro el tamaño de los shards?

Cuando usa índices temporales, en general, cada uno de estos ha estado asociado con un período fijo. Los índices diarios son muy comunes y, a menudo, se usan para contener datos con un período de retención breve o con volúmenes diarios significativos. Estos permiten que el período de retención se administre con una buena granularidad y facilitan el ajuste para modificar los volúmenes a diario. Los datos con un período de retención más extenso, especialmente si los volúmenes diarios no garantizan el uso de índices diarios, a menudo usan índices semanales o mensuales para mantener el tamaño del shard. Esto reduce la cantidad de índices y shards que deberán almacenarse en el cluster con el tiempo.


CONSEJO: Si usa índices temporales que cubran un período fijo, ajuste el período que cubre cada índice en función del período de retención y los volúmenes de datos previstos, a fin de lograr el tamaño de shard deseado.


Los índices temporales con un intervalo de tiempo fijo funcionan perfectamente cuando los volúmenes de datos pueden predecirse de forma razonable y cambian lentamente. Si la tasa de indexación puede variar rápidamente, es muy difícil mantener un tamaño de shard deseado uniforme.

A fin de poder resolver mejor este tipo de situaciones, se introdujeron las API de rollover y shrink. Estas API aportan flexibilidad a la forma en que se administran los índices y los shards, especialmente para los índices temporales.

La API de rollover permite especificar la cantidad de documentos que debe contener un índice o el período máximo en que los documentos deben escribirse en este. Una vez que se cumplan estos criterios, Elasticsearch puede desencadenar la creación de un nuevo índice para escribir sin caída de servicio. En lugar de que cada índica cubra un período específico, ahora es posible cambiar a un nuevo índice de un tamaño particular. Esto permite lograr un tamaño uniforme de shard para todos los índices con mayor facilidad.

En los casos en que los datos se actualicen, al usar esta API, ya no habrá un vínculo distintivo entre el timestamp del evento y el índice en que reside, ya que esto puede afectar la eficiencia de las actualizaciones de forma significativa, debido a que debe realizarse una búsqueda antes de la actualización.


CONSEJO: Si cuenta con datos inmutables temporales, cuyos volúmenes varían significativamente con el tiempo, considere usar la API de rollover para lograr el tamaño de shard deseado óptimo al variar de forma dinámica el período que cubre cada índice. Esto proporciona gran flexibilidad y puede evitar shards muy grandes o muy pequeños cuando los volúmenes son impredecibles.


La API de shrink le permite reducir un índice para convertirlo en uno nuevo con menos shards primarios. Si desea una distribución más uniforme de los shards a lo largo de los nodos durante la indexación, pero esto tendría como resultado shards demasiado pequeños, esta API puede usarse para reducir la cantidad de shards primarios una vez que ya no se indexa en el índice. Esto generará shards más grandes, mejores para almacenar datos a largo plazo.


CONSEJO: Si necesita que cada índice cubra un período específico, pero desea poder distribuir la indexación a lo largo de una gran cantidad de nodos, considere usar la API de shrink para disminuir la cantidad de shards primarios una vez que ya no se indexa en el índice. Esta API también puede usarse para reducir la cantidad de shards si inicialmente configuró demasiados.


Conclusiones

Este artículo del blog le ofrece consejos y pautas prácticas sobre cómo administrar datos con mayor eficacia en Elasticsearch. Si está interesado en obtener más información, «Elasticsearch: La guía definitiva» contiene una sección acerca del diseño en escala que vale la pena leer, a pesar de su antigüedad.

No obstante, muchas de las decisiones sobre cómo distribuir mejor sus datos a lo largo de índices y shards dependerán de las particularidades del caso de uso. A veces puede ser complejo determinar cuál es la forma óptima de aplicar las pautas disponibles. Para obtener consejos más detallados y personalizados, puede contactarnos mediante una suscripción comercial y dejar que nuestros equipos de Soporte y Consultoría lo ayuden a acelerar su proyecto. Si se siente cómodo para analizar su caso de uso abiertamente, puede obtener ayuda de parte de nuestra comunidad a través del foro público.