viernes, junio 10, 2011

¿Es lento Lucene en tiempo real?

A través de este twit de Marc Sturlese, llego a un fenomenal artículo de Mike McCandless, miembro del proyecto Lucene y autor de la segunda edición de Lucene in Action, en el que se hace un exhaustivo análisis de las capacidades de Lucene para realizar búsquedas en tiempo real.

La capacidad para realizar búsquedas en tiempo real se habilitó en Lucene desde la versión 2.9. Es una funcionalidad trivial de añadir, tan sólo una línea de código, pero de bastante complejidad interna. La clave del funcionamiento está en que permite buscar cambios que todavía no han sido guardados en los índices de Lucene, con lo que se obtienen unos resultados, como bien dice el nombre, cercanos a lo que sería tiempo real. Cercanos porque cada vez que intentas realizar una búsqueda en tiempo real, utilizas lo que ellos llaman Reader, y ahí es como si se parase el tiempo, te ofrece acceso a todos los datos que había hasta ese momento en el índice, y como decía incluso aquellos que no habían sido guardados todavía. Pero vamos, que existe una pequeña ventana hacia adelante en el tiempo que no nos devolverá, pero muy despreciable desde el punto de vista de las aplicaciones.

// w is your IndexWriter
IndexReader r = IndexReader.open(w, true);


¿Y esto es rápido? Pues parece que sí. El experimento realizado es bastante fuerte. El autor primero indexó todos los documentos de la Wikipedia. 25 Gb utilizando bloques de 1Kb. Posteriormente, el test se encarga de reindexar los documentos a un ritmo de 1MB/s, que es básicamente el doble de la carga de Twitter en la Superbowl (+4000 twits por segundo). Utilizó un servidor con 24 núcleos (dual x5680 Xeon CPUs), con una SSD de 340Gb, JVM de 64 bits y 2Gb de Heap. Y con esas condiciones el test se puso a hacer búsquedas durante 6 horas que es lo que duró el reindexado. Básicamente se trata de unas condiciones extremas con una altísima tasa de escrituras (reindexados), prácticamente imposibles para la inmensa mayoría de las aplicaciones de hoy en día. El resultado fue el siguiente (podéis hacer click en el gráfico para ver los datos. Es un javascript.):



Básicamente se puede apreciar como la capacidad para hacer búsquedas se va degradando poco a poco con el tiempo, pero ojo, que estamos hablando de 6 horas continuadas de carga brutal. Tiene que ver con la forma en la que Lucene maneja los borrados de documentos viejos, y en el post explican algunas posibles soluciones si esto puediese ser un problema, que realmente no lo es. Asimismo, la tasa de búsquedas se mantuvo constante entre los 100 y 150 búsquedas por segundo. Bastante impresionante para el volumen de escrituras que hay.

Bien el artículo sigue con más análisis e ideas, pero sería ya muy largo de explicar. Sin embargo al final nos cuenta algunos trucos para mejorar la respuesta de nuestro Lucene, que sí que me gustaría dejar aquí reflejados:

  • Utilizar un sistema de entrada y salida rápido. Básicamente SSD hoy por hoy.

  • Preparar Lucene para que no cueste tanto reabrir los índices (usar warmers)

  • Cuantas menos Threads usemos para indexar, mejor. Menos threads = flush más rápidos = menos merges

  • Utilizar el nuevo codec, Pulsing, para las ids si estamos con la trunk de lucene. Mucho más rendimiento.

  • Utilizar el nuevo NRTCachingDirectory, que guarda documentos en RAM para no cargar tanto el disco con las búsquedas en tiempo real.

  • No borrar los documentos (false en applyDeletes) para los NRT Readers, si la aplicación es capaz de tolerar el recibir documentos que han sido borrados.

  • Configurar bien las prioridades de los hilos. El Thread que reabre el índice debería tener la prioridad más alta, después los hilos indexadores y por último los hilos de las búsquedas.



Ya veis. Una línea de código que da para mucho, mucho.

No hay comentarios:

Publicar un comentario