Vida útil después de 1 año de usar Neo4J

Hace un año, en uno de mis proyectos, tuvimos la idea de que migrar a Neo4j sería genial, porque tenemos datos que serían ideales para graficar. Después de eso, nuestra vida cambió para siempre.

Creo que Neo4j es como una heroína, primero piensas que es lo más asombroso que puedas imaginar, pero después de unos meses eyforiya decae y comienzas a entender que tal vez no fue la mejor opción en tu vida.
En el sitio de Neo4j puede ver muchos clientes importantes como Ebay, LinkedIn, pero en realidad no sé cómo ni dónde están usando esta base de datos, así que si algunos de sus desarrolladores pueden compartir información en los comentarios, sería estupendo. Pero por ahora solo les contaré mi experiencia personal con el uso de Neo4j.

Idioma de consulta

El lenguaje de consulta de Neo4j se llama Cypher. Es muy simple y después de unos minutos de lectura de documentos, ya puede realizar algunas consultas no triviales. Como la mayoría de las bases de datos, también tiene los comandos Explain y Profile , que le brindan la posibilidad de comprender lo que está sucediendo bajo el capó de la consulta.
Pero cuando comienzas a hacer consultas cada vez más complejas, empiezas a ver que no puedes entender cómo funciona la consulta, y después de cada cambio necesitas usar Perfil . Por ejemplo, en SQL, cuando usa la directiva Join, ya sabe que esto hará que la consulta sea más pesada, pero en Neo4j puede cambiar el orden de algunas filas que lógicamente no conducen a ningún cambio, pero en tiempo de ejecución puede aumentar el tiempo de consulta de 0.05 ms a 30 seg. Entonces, hacer consultas difíciles es una especie de magia. Creo que esa es una de las razones por las que los chicos de Neo4j recomiendan dividir todas las consultas en consultas pequeñas.

Ejecución de la consulta

Observador de consultas
De modo que realiza su primera consulta y la ejecuta en el servidor, pero desafortunadamente comete un pequeño error que devuelve no 5 nodos sino 5M nodos. En la mayoría de las bases de datos hay un observador que busca consultas de larga duración o consultas que utilizan una gran cantidad de memoria y puede eliminarlas para evitar que la base de datos se caiga. Neo4j by docs también tiene uno, pero no vi que realmente funcionara. En el mejor de los casos, obtendrá un error como “indefinido – indefinido”, en el peor de los casos, su base de datos se caerá y tal vez su servidor también.

Leer todos los datos primero
Recuerde, en Neo4j no importa lo que esté haciendo, primero hará la consulta de lectura. Entonces, por ejemplo, en la base de datos relacional, desea eliminar todos los registros: Db revisará cada registro y los eliminará, y no importa cuántos los tenga. En Neo4j, primero intentará obtener toda la información de estos registros y luego ejecutará eliminar. En la vida real, esto significa, por ejemplo, que no puede eliminar todos los registros de 1 millón de la base de datos, porque simplemente no tiene mucha RAM para eso. Y para eliminarlos todos, deberá crear un script que ejecute consultas con Límite hasta que se eliminen todos los registros. El problema es que no puede saber cuántos datos hay en el nodo y cómo establecer el límite para que no se desborde de la RAM.

Bloquear
Esa es otra parte divertida. El bloqueo funciona aquí de una manera diferente que en muchas bases de datos relacionales. Entonces, por ejemplo, en alguna base de datos rel cuando realiza una consulta de actualización, el ejecutor de la consulta lo comprende y establece el bloqueo de escritura para el campo, el registro, etc. En Neo4j solo hay un bloqueo de escritura que se establece no antes de que la consulta comience a ejecutarse, sino cuando parte de la consulta intentará actualizar algo. Entonces, por ejemplo, la consulta MATCH (n: Test {id: 1}) SET n.param = 2 agregará bloqueo de escritura al nodo solo después de realizar la solicitud MATCH. Y eso significa que en las actualizaciones simultáneas tendrás problemas. Hay un gran tema en el blog de Neo4j sobre cómo manejar estos problemas, pero para mí parece una colección de soluciones urgentes. Aquí está: https://neo4j.com/blog/advanced-neo4j-fiftythree-reading-writing-scaling/

Conexiones

Otro problema cuando está funcionando: no hay un balanceador de proxy de conexión como en Pg, y tampoco hay forma de limitar el número de conexiones que DB puede manejar y cerrar otras. Esto llevó a usar HAproxy y extraños scripts escritos a mano para lograr esto y hacer que DB sea más estable para uso en vivo.

Alta disponibilidad

Neo4j solo tiene una forma de hacerlo y básicamente es una replicación maestro-esclavo, ni siquiera tiene una replicación maestra. Además, no hay forma de establecer la prioridad maestra para las instancias (lo cual es bueno cuando ha instalado complementos. Les contaré más sobre ellos).

Entonces, por ejemplo, no puede hacer una replicación DC-DC, no puede usar la técnica de implementación azul verde o hacer dos clústeres. Todas estas cosas las tendrás que hacer tú mismo escribiendo scripts, servicios y complementos del kernel para Neo4J.
También los desarrolladores de Neo4j en su blog también escribieron que siempre debes verificar la sincronización entre maestro y esclavo porque a veces puede fallar.

Extensiones

Entonces, hay 3 tipos de extensiones para Neo4j: extensiones no administradas, complementos de servidor y extensiones de kernel. Estaba trabajando solo con el tercero.
Las extensiones de kernel se usan cuando necesitas agregar alguna funcionalidad adicional al funcionamiento interno de Neo4j. En mi caso, estaba trabajando con TransactionEventHandler, que solía trabajar con eventos de transacciones como beforeCommit, afterCommit, afterRollback.

Me parece una buena forma de agregar algunas funciones que Neo4j no tiene en la caja.

Lo primero que entiendo es que casi no hay documentación para eso, y tuve que revisar algunos complementos creados, StackOverflow y otros sitios para juntar las cosas y hacer el primer intento (tal vez si tuviera un desarrollador de Java lo haría ser mucho más rápido, pero principalmente trabajo con Python y, a veces, con Android).

Lo segundo que encontré es que no todos los eventos funcionan como deberían. Entonces, por ejemplo, en beforeCommit (que debe ejecutarse cuando la base de datos no cambia) no puede acceder a los parámetros, etiquetas y relaciones de los nodos eliminados porque ya están eliminados. Sí … extraño. Luego afterCommit (que debe ejecutarse después de confirmar y cerrar la transacción) se ejecuta cuando la transacción aún está abierta, lo que conducirá a un punto muerto (sin información ni excepción) si intenta actualizar su base de datos local (en algunos casos).

En tercer lugar, cada extensión se ejecuta en un entorno global que conduce a colisiones de dependencias, que si tiene más de un complemento, lo llevará a arreglar los complementos para su caso manualmente.

Escribí un ejemplo para Kernel Extension que puede ayudar a comenzar a crear un nuevo complemento interesante: https://github.com/creotiv/neo4j-kernel-plugin-example

Mi conclusión

Por lo tanto, no digo que Neo4j no funcione, ya que sé que es una de las mejores bases de datos de gráficos que puede usar de forma gratuita, pero sigue siendo muy cruda. Y debe comprender que si su tarea no es muy trivial, obtendrá algunos gastos generales para que funcione con Neo4j. Además, no se ajusta muy bien a los requisitos de HL + HA.

Me alegraría que pudieran compartir su experiencia de trabajar con Neo4j aquí en los comentarios.

Lea mi nueva historia



Hacker Noon es la forma en que los piratas informáticos comienzan sus tardes. Somos parte de la familia @AMI. Ahora estamos aceptando envíos y estamos felices de discutir sobre publicidad y amp; oportunidades de patrocinio.

Si te gustó esta historia, te recomendamos leer nuestras últimas historias tecnológicas y las historias tecnológicas más populares. ¡Hasta la próxima, no dé por sentadas las realidades del mundo!