Elasticsearch como base de datos NoSQL
ACTUALIZACIÓN: En este artículo se hace referencia a nuestra oferta de Elasticsearch hospedado con su nombre anterior, Found. Ten en cuenta que Found ahora es conocido como Elastic Cloud. Hay pruebas de 14 días de Elasticsearch hospedado sin costo en Elastic Cloud.
¿Puede usarse Elasticsearch como una base de datos "NoSQL"? NoSQL significa diferentes cosas en distintos contextos, y lo más curioso es que no se relaciona con SQL en realidad. Comenzaremos con un "tal vez" y veremos las distintas propiedades de Elasticsearch, además de las que ha sacrificado, que le han permitido convertirse en uno de los motores de analítica y búsqueda más flexibles y de mejor rendimiento hasta ahora.
Para empezar, ¿qué es una base de datos NoSQL?
NoSQL-database define NoSQL como "bases de datos de próxima generación que abordan principalmente algunos de los puntos: no relacionales, distribuidos, open source y escalables horizontalmente". En otras palabras, la definición no es muy precisa.
No está relacionada con SQL en particular. Por ejemplo, el lenguaje de búsqueda de Hive claramente está inspirado en SQL. Lo mismo sucede con el lenguaje de búsqueda de Esper, que opera a partir de flujos, en lugar de relaciones. Además, ¿sabías que PostgreSQL se llamaba "Postgres" y tenía "Quel" como lenguaje de búsqueda en un principio? Si bien ante todo es un ORDBMS, ahora también tiene muchas características que lo hacen viable como almacén de documentos sin esquema.
Tampoco se relaciona con ACID. Hyperdex es un ejemplo de una base de datos NoSQL cuyo objetivo es brindar transacciones ACID. MySQL, definitivamente una base de datos SQL, tiene antecedentes de interpretaciones ambiguas en cuanto al significado real de ACID.
¿Relaciones? Si bien la mayoría de las bases de datos NoSQL no soportan la combinación del mismo modo que las bases de datos relacionales tradicionales y dejan que el usuario se encargue de eso, algunas sí lo admiten. RethinkDB, Hive y Pig, entre otras. Neo4j, una base de datos orientada a grafos, sin dudas involucra relaciones; es excelente para examinar las relaciones (es decir, los extremos) en los grafos. Elasticsearch tiene un concepto de combinación del "tiempo de búsqueda" con relaciones principales/secundarias y combinación del "tiempo de indexación" con tipos anidados.
¿Distribuidas? Si bien hay algunas bases de datos SQL distribuidas, y algunos proyectos que apuntan a algo como NoSQLite, las bases de datos de generaciones más recientes tienden a ser distribuidas de una u otra forma.
A modo de resumen más breve, no tiene sentido definir con precisión NoSQL ni decir simplemente que Elasticsearch es una base de datos NoSQL de tipo "almacén de documentos". Al momento de escribir este blog, nosql-database.org enumera >20 de estas.
En las secciones siguientes, veremos algunas propiedades importantes y cómo Elasticsearch las implementa o no.
Sin transacciones
Lucene, sobre lo cual está desarrollado Elasticsearch, tiene una noción de las transacciones. Por otro lado, Elasticsearch no tiene transacciones en el sentido típico. No hay forma de revertir un documento enviado, tampoco puedes enviar un grupo de documentos y hacer que todos o ninguno se indexen. Sin embargo, sí posee un log de escritura anticipada para garantizar la durabilidad de las operaciones sin necesidad de una costosa confirmación de Lucene. También puedes especificar el nivel de consistencia de las operaciones de indexación, en cuanto a la cantidad de réplicas que deben reconocer la operación antes de la devolución. De forma predeterminada, es la mayoría, es decir \(\lfloor\frac{n}{2}\rfloor + 1\).
La visibilidad de los cambios se controla cuando se actualiza un índice, lo que ocurre de manera predeterminada una vez por segundo y shard por shard.
El control de concurrencia optimista se realiza especificando la versión de los documentos enviados.
Elasticsearch fue creado para la velocidad. Realizar transacciones distribuidas requiere mucho trabajo. No proporcionarlas, facilita muchas cuestiones. Si aceptamos que lo que leemos puede ser en cierta medida obsoleto y que todos vemos la misma línea de tiempo, Elasticsearch puede proporcionar muchas cosas a partir de las memorias caché (esencial para la mente) y sorprender con el rendimiento por el que nos encanta.
Flexibilidad de esquemas
Elasticsearch no requiere que especifiques un esquema por anticipado. Si le arrojas un documento JSON, intentará predecir de manera fundamentada su tipo. Hace un buen trabajo con valores numéricos, booleanos y marcas de tiempo. En el caso de cadenas, usará el analizador "estándar", que suele ser un buen punto de partida.
Si bien puede decirse que es "libre de esquemas", en el sentido de que no necesitas especificar uno, en su lugar, nos gusta pensar que tiene "flexibilidad de esquemas". Para desarrollar una búsqueda o analíticas excelentes, debes modificar tus esquemas. Elasticsearch cuenta con un amplio conjunto de herramientas poderosas para ayudarte, como plantillas dinámicas, objetos multicampo, etc. Esto se abarca en más detalle en nuestro artículo sobre mapeo.
Relaciones y restricciones
Elasticsearch es una base de datos orientada a documentos. El objeto grafo completo en el que deseas buscar debe estar indexado, por lo tanto, antes de indexar tus documentos, deben desnormalizarse. La desnormalización aumenta el rendimiento de recuperación (dado que no es necesaria la combinación de búsquedas) y usa más espacio (porque los elementos deben almacenarse varias veces), pero dificulta mantener la consistencia y los datos actualizados (dado que cualquier cambio debe aplicarse en todas las instancias). Sin embargo, es una opción excelente para cargas de trabajo de tipo escritura única y lectura múltiple.
Supongamos, por ejemplo, que configuraste una base de datos con clientes, pedidos y productos, y deseas buscar los pedidos por el nombre de un producto y usuario. Esto podría resolverse indexando los pedidos con toda la información necesaria sobre el usuario y los productos. Buscar resulta sencillo, pero ¿qué sucede cuando deseas cambiar el nombre del producto? En un diseño relacional con normalización adecuada, simplemente podrías actualizar el producto y estaría hecho. Para eso son muy buenos. En una base de datos de documentos desnormalizada, debería actualizarse cada pedido con dicho producto.
En otras palabras, en bases de datos orientadas a documentos, como Elasticsearch, diseñamos los mapeos y almacenamos los documentos de manera que se optimicen para la búsqueda y la recuperación.
Como mencionamos al comienzo, Elasticsearch tiene un concepto de combinación del "tiempo de búsqueda" con relaciones principales/secundarias y combinación del "tiempo de indexación" con tipos anidados. Probablemente profundicemos sobre esto en un próximo artículo. Mientras, podemos recomendar la presentación de Martijn van Groningen "Document relations with Elasticsearch" (Relaciones de documentos con Elasticsearch).
La mayoría de las bases de datos relacionales también te permiten especificar restricciones para definir qué es consistente y qué no. Por ejemplo, pueden aplicarse la exclusividad y la integridad referencial. Puedes requerir que la suma de los movimientos de la cuenta sea positiva, entre otras cosas. Las bases de datos orientadas a documentos tienden a no hacer esto, y Elasticsearch no es distinto.
Solidez
Una base de datos debe ser sólida, en particular si es tu sistema de registro oficial. Idealmente, una búsqueda costosa debería poder cancelarse, y sin dudas no quieres que la base de datos deje de funcionar a menos que lo indiques.
Desafortunadamente, Elasticsearch (y los componentes que lo conforman) no lidia bien en la actualidad con errores OutOfMemory. Vemos esto en más detalle en Elasticsearch en producción, fallas provocadas por OutOfMemory. Es muy importante proporcionar a Elasticsearch la memoria suficiente y tener cuidado antes de ejecutar búsquedas con requisitos de memoria desconocidos en un cluster de producción.
Si bien es probable que esto mejore a medida que Elasticsearch madure, es importante recordar que Elasticsearch se desarrolló para la velocidad, suponiendo que la memoria es abundante.
Distribuido
Ve también: Elasticsearch en producción, redes.
Antes de que Shay Banon creara Elasticsearch, había estado trabajando en Compass. Al darse cuenta de que sería difícil convertirlo en un motor de búsqueda distribuido, comenzó desde cero y creó Elasticsearch1. Elasticsearch se desarrolló para ser distribuido y fácil de escalar horizontalmente para ocuparse de enormes cantidades de datos en hardware comercial.
Es increíblemente fácil dar los primeros con Elasticsearch y usarlo en un sistema distribuido, pero los sistemas distribuidos son complicados. Hablamos un poco más al respecto en Elasticsearch en producción, redes, por lo que lo siguiente es un breve resumen.
La propia naturaleza de un sistema distribuido implica una gran cantidad de cuestiones que pueden salir mal. Por lo cual, los distintos sistemas de bases de datos se enfocan en diferentes fortalezas: algunos apuntan a garantías sólidas, otros a estar siempre disponibles, a pesar de tener errores algunas veces (o la mayoría). Además, lo que un sistema de base de datos proclama lograr cuando ocurren problemas no suele ser lo que en realidad enfrenta, tal como explora Kyle Kingsbury en su espectacular serie sobre los riesgos de las particiones de red. En pocas palabras, descubre que si bien las bases de datos distribuidas funcionan bien los días buenos, la mayoría tiene problemas ante una gran cantidad de formas posibles de falla.
En cuanto a la tolerancia a particiones, disponibilidad y consistencia, Elasticsearch es un sistema CP, para una definición bastante deficiente de "consistente". Si tienes una carga de trabajo de solo lectura. Elasticsearch te permite lograr un comportamiento AP gracias a un requisito de "nodos maestros mínimo" flexible, es decir, que no requiere una mayoría. Sin embargo, en general, necesitarás que la mayoría de los nodos en el cluster estén disponibles. Escribir en un cluster mal configurado sin esta mayoría, es decir, un cluster "disociado", puede dar como resultado una pérdida de datos irrecuperable. Esto no es para nada propio de Elasticsearch.
En términos de escalado, un índice se divide en uno o más shards. Esto se especifica cuando se crea el índice y no puede modificarse. Por lo tanto, un índice debe dividirse en shards de forma proporcional con el crecimiento anticipado. A medida que se agregan más nodos a un cluster de Elasticsearch, hace un buen trabajo reasignando y acomodando los shards. Como tal, Elasticsearch es muy fácil de escalar horizontalmente.
Seguridad
Ve también: Elasticsearch en producción, seguridad.
Elasticsearch no posee características de autenticación ni de autorización. Deberías considerar que todo aquel que pueda conectarse al cluster de Elasticsearch tiene derechos de "superusuario", especialmente si están habilitadas las capacidades de scripting poderosas de Elasticsearch.
Resumen
Definitivamente es posible usar Elasticsearch como almacén principal, cuando las limitaciones descritas no son impedimentos. Un buen ejemplo es con el uso de Logstash. Logstash es una herramienta fantástica para gestionar logs e introducirlos en Elasticsearch, y tal vez también archivarlos en algún otro sitio, por las dudas. Los logs se escriben una vez, pero se leen muchas. No se necesita actualización, no se necesitan transacciones, restricciones de integridad, etc.
¿Y los sistemas como Postgres, que incluyen búsqueda de texto completo y transacciones ACID? (Otros ejemplos son las capacidades de texto completo de MySQL, MongoDB, Riak, etc.). Si bien puedes implementar la búsqueda básica con Postgres, hay una gran brecha tanto en el rendimiento posible como en las características. Tal como se menciona en la sección sobre transacciones, Elasticsearch puede "hacer trampa" y almacenar en caché, sin preocuparse por el control de concurrencia multiversión y otras cuestiones que presentan complicaciones. La búsqueda es más que encontrar una palabra clave en un fragmento de texto: es aplicar conocimiento específico del dominio para implementar buenos modelos de relevancia, brindar una visión general del espacio de resultado completo y realizar tareas como revisión ortográfica y autocompletado. Todo esto sin perder la rapidez.
Elasticsearch suele usarse junto con otra base de datos. Un sistema de base de datos con mayor foco en las restricciones, la corrección y la solidez, y en estar listo y permitir actualizaciones respecto a las transacciones, tiene el registro maestro; el cual luego se envía de forma asíncrona a Elasticsearch. (O se extrae, si usas uno de los "ríos" de Elasticsearch). Mantener la sincronización es algo que veremos en detalle en un próximo artículo. Aquí, en Found, por lo general usamos PostgreSQL y ZooKeeper como guardianes de la información, la cual alimentamos a Elasticsearch para una búsqueda increíble.
Como con todo lo demás, no hay una solución mágica, ninguna base de datos gobierna a todos. Lo más probable es que siempre sea así, por lo que te recomendamos conocer las fortalezas y debilidades de tus almacenes.
Referencias
Banon, Shay: The future of compass & elasticSearch (El futuro de Compass y Elasticsearch) – https://thedudeabides.com/articles/the_future_of_compass
- Shay Banon, The future of compass & elasticSearch (El futuro de Compass y Elasticsearch) – https://thedudeabides.com/articles/the_future_of_compass.↩