Cuando agrego 200 documentos a ElasticSearch a través de una solicitud masiva, es súper rápido.

Pero me pregunto si existe la posibilidad de acelerar el proceso con ejecuciones concurrentes : 20 ejecuciones concurrentes con 10 documentos cada una.

Sé que no es eficiente, pero ¿existe la posibilidad de acelerar el proceso con ejecuciones concurrentes?

1
Lajtovo 20 feb. 2020 a las 22:46

2 respuestas

La mejor respuesta

Se prefiere una menor concurrencia para las inserciones de documentos en masa. Alguna concurrencia es útil en algunas circunstancias (depende de ™ y lo abordaré), pero no es una victoria importante o automática.

Hay muchas cosas que se pueden ajustar cuando se trata del rendimiento de las escrituras en Elasticsearch. Una victoria realmente rápida que deberías comprobar: ¿estás usando HTTP keep-alive para tus conexiones? Eso ahorrará una gran cantidad de sobrecarga de TCP y TLS al configurar cada conexión. Solo ese cambio puede hacer un gran aumento de rendimiento y también descubrir algunas consideraciones arquitectónicas significativas para su canalización de indexación.

Así que échale un vistazo y mira cómo va. A partir de ahí, debemos ir al fondo y avanzar.

El índice en el disco es Lucene. Lucene es un índice segmentado. La parte index es una razón central por la que está usando Elasticsearch en primer lugar: se puede buscar un diccionario de términos ordenados en tiempo O (log N). Eso es súper rápido y escalable. La parte del segmento se debe a que la inserción en un índice no es particularmente rápida; dependiendo de su implementación, le cuesta a O (log N) u O (N log N) mantener la clasificación.

El truco de Lucene es amortiguar esas actualizaciones y agregar un nuevo segmento; esencialmente una colección de mini-índices. Buscar un número relativamente pequeño de segmentos es aún mucho más rápido que tomarse todo el tiempo para mantener un índice ordenado con cada actualización. Con el tiempo, Lucene se encarga de fusionar estos segmentos para mantenerlos dentro de un rango de tamaño razonable, eliminando documentos eliminados y sobrescritos en el proceso.

En Elasticsearch, cada fragmento es un índice Lucene distinto. Si tiene un índice con un solo fragmento, entonces hay muy pocos beneficios de tener más de una secuencia simultánea de actualizaciones masivas. Puede haber algún beneficio en la concurrencia en el lado de la aplicación, dependiendo de la cantidad de tiempo que le lleve a su canalización de indexación recopilar y ensamblar cada lote de documentos. Pero en el lado de Elasticsearch, todo es solo un conjunto de buffers que se escriben en un segmento tras otro.

Sharding lo hace un poco más interesante.

Una de las fortalezas de Elasticsearch es la capacidad de particionar los datos de un índice a través de múltiples fragmentos. Esto ayuda con la disponibilidad y ayuda a escalar las cargas de trabajo más allá de los recursos de un solo servidor.

Por desgracia, no es tan simple como para decir que la concurrencia debe ser igual o proporcional al número de fragmentos primarios que tiene un índice. Aunque, como una heurística aproximada, no es terrible.

Verá, internamente, el primer nodo de Elasticsearch para manejar la solicitud va a convertir esa solicitud en masa en una secuencia de acciones de actualización de documentos individuales. Cada actualización de documento se envía al nodo apropiado que aloja el fragmento al que pertenece este documento. La acción masiva recopila las respuestas para que pueda enviar un resumen de la operación masiva en su respuesta al cliente.

Entonces, en este punto, dependiendo del enrutamiento de fragmentos de documentos, algunos fragmentos pueden estar más ocupados que otros durante el proceso de procesamiento de una solicitud masiva entrante. ¿Es probable que eso importe? Mi intuición dice que en realidad no. Es posible, pero sería inusual.

En la mayoría de las pruebas y análisis que he visto, y en mi experiencia de más de diez años con Lucene, la parte lenta de la indexación es la transformación de los valores de los documentos en el formato de índice invertido. Analizar el texto, analizarlo en términos, etc., puede ser muy complejo y costoso. Siempre que una solicitud masiva tenga suficientes documentos que estén suficientemente bien distribuidos entre fragmentos, la concurrencia no es tan significativa como saturar el trabajo realizado a nivel de fragmento y segmento.

Al ajustar solicitudes masivas, mi consejo es algo como esto.

  • Utiliza HTTP keep-alive. Esto no es opcional. (Estás utilizando TLS, ¿verdad?)
  • Elija un tamaño de lote en el que cada solicitud tarde un tiempo modesto. En algún lugar alrededor de 1 segundo, probablemente no más de 10 segundos.
  • Si puede ser elegante, mida cuánto tiempo tomó cada solicitud masiva y aumente y reduzca dinámicamente su lote.

Una cola duradera desbloquea muchas capacidades. Si puede buscar y ensamblar documentos e insertarlos en, por ejemplo, Kafka, entonces ese proceso puede ejecutarse en paralelo para saturar la base de datos y paralelizar cualquier desnormalización o preparación de documentos. Luego, un proceso diferente se extrae de la cola y envía solicitudes al servidor, y con una coordinación ligera puede probar y ajustar diferentes concurrencias en diferentes etapas. Una cola también le permite pausar sus actualizaciones para diversas migraciones y tareas de mantenimiento cuando ayuda a poner el clúster en modo de solo lectura durante un tiempo.

He evitado la replicación a lo largo de esta respuesta porque solo hay una razón por la que recomendaría ajustar la replicación. Y eso es cuando está creando en masa un índice que no está sirviendo ningún tráfico de producción. En ese caso, puede ayudar a ahorrar algunos recursos a través de su flota de servidores para desactivar toda la replicación en el índice y habilitar la replicación después de que el índice se haya cargado esencialmente con datos.

Para cerrar, ¿qué pasa si aumenta la concurrencia de todos modos? ¿Cuál es el riesgo? Algunas cargas de trabajo no controlan la concurrencia y no hay tiempo ni recursos para poner una cola frente al motor de búsqueda. En ese caso, Elasticsearch puede evitar una cantidad bastante considerable de concurrencia. Tiene grupos de subprocesos bastante generosos para manejar actualizaciones de documentos concurrentes. Si esos grupos de subprocesos están saturados, rechazará las respuestas con un mensaje de error HTTP 429 y un mensaje claro sobre las profundidades de la cola que se exceden. Esos pueden afectar la estabilidad del clúster, dependiendo de los recursos disponibles y el número de fragmentos en el índice. Pero esos son todos problemas bastante notables.

En pocas palabras: no, 20 lotes simultáneos con 10 documentos cada uno probablemente no acelerarán el rendimiento en relación con 1 lote con 200 documentos. Si sus operaciones masivas son rápidas, debe aumentar su tamaño hasta que se ejecuten por un segundo o dos, o sean problemáticas. Use keep-alive. Si hay otros gastos generales en el lado de la aplicación, aumente su concurrencia a 2x o 3x y mida empíricamente. Si la indexación es crítica, utilice una cola rápida y duradera.

3
Nick Zadrozny 21 feb. 2020 a las 20:38

No hay una respuesta directa a esto, ya que depende de muchos factores. Por encima del tamaño óptimo de solicitud masiva, el rendimiento ya no mejora e incluso puede disminuir. El tamaño óptimo, sin embargo, no es un número fijo.

Depende completamente de su hardware, el tamaño y la complejidad de su documento, y su carga de indexación y búsqueda.

Intente indexar documentos típicos en lotes de tamaño creciente. Cuando el rendimiento comienza a disminuir, el tamaño de su lote es demasiado grande.

Como lo está haciendo en lotes de 200, hay muchas posibilidades de que sea la forma más óptima de indexar. Pero nuevamente dependerá de los factores mencionados anteriormente.

0
Ashish Modi 20 feb. 2020 a las 20:31
60327480