Cómo adoptar el análisis gráfico basado en eventos usando Neo4j y Apache Kafka

Foto de rawpixel en Unsplash

Introducción

Con las nuevas transmisiones de Neo4j Kafka ahora disponibles, mi colega compañero de Neo4j, Tom Geudens, y yo estábamos ansiosos por probarlo. Tenemos en mente muchos casos de uso que aprovechan el poder de las bases de datos de gráficos y las arquitecturas basadas en eventos. El primero que exploramos combina el poder de los algoritmos gráficos con una base de datos transaccional.

La nueva biblioteca de transmisiones Neo4j Kafka es un complemento de Neo4j que puede agregar a cada una de sus instancias de Neo4j. Permite tres tipos de mecanismos de Apache Kafka:

  • Productor: basado en los temas configurados en el archivo de configuración de Neo4j. Las salidas a dichos temas sucederán cuando el nodo especificado o los tipos de relación cambien
  • Consumidor: según los temas configurados en el archivo de configuración de Neo4j. Cuando se recogen eventos para dichos temas, se ejecutará la consulta Cypher especificada para cada tema
  • Procedimiento: una llamada directa en Cypher para publicar una carga útil dada a un tema específico

Puede obtener una descripción más detallada de cómo se vería cada uno de estos aquí.

Resumen de la situación

Los algoritmos de gráficos proporcionan potentes habilidades analíticas. Nos ayudan a comprender mejor el contexto de nuestros datos mediante el análisis de las relaciones. Por ejemplo, los algoritmos gráficos se utilizan para:

  • Comprender las dependencias de red
  • Detectar comunidades
  • Identificar personas influyentes
  • Calcular recomendaciones
  • Etcétera.

Neo4j ofrece un conjunto de algoritmos gráficos listos para usar a través de un complemento que puede ejecutarse directamente en los datos dentro de Neo4j. Esta biblioteca de algoritmos ha sido muy popularmente recibida. Muchas veces he recibido comentarios de que los complementos son tan rápidos o más rápidos que lo que los clientes han usado antes. Con una respuesta tan maravillosa, ¿por qué no queremos aplicar estos algoritmos optimizados y de alto rendimiento en una base de datos Neo4j?

Las categorías del algoritmo gráfico Neo4j

Obtener la máxima ventaja de cualquier proceso analítico necesita recursos. Para obtener una experiencia agradable y eficiente, queremos proporcionar tanta CPU y memoria como podamos.

Ahora, podríamos ejecutar este tipo de trabajo en nuestro clúster transaccional. Pero en esta arquitectura típica, nos enfrentaremos a algunos desafíos. Por ejemplo, si una máquina es grande, las otras máquinas del clúster deberían coincidir. Esto podría significar que la arquitectura de configuración es costosa.

El otro desafío al que nos enfrentamos es que se supone que nuestro clúster debe administrar transacciones, consultas diarias, como el procesamiento de solicitudes. No queremos sopesarlo con el crujido a través de varias iteraciones y permutaciones de un modelo. Idealmente, queremos descargar esto junto con el trabajo analítico asociado.

Si sabemos que las consultas pesadas que se realizarán son de solo lectura, entonces es una solución fácil. Podemos girar réplicas de lectura para administrar la carga. Esto mantiene al clúster enfocado en lo que se supone que debe estar haciendo, apoyando un sistema operacional y transaccional.

Pero, ¿cómo manejamos las reescrituras en el gráfico operativo como parte del procesamiento analítico? Queremos esos resultados, como recomendaciones, tan pronto como estén disponibles.

Las réplicas de lectura son como su nombre indica: son para aplicaciones de solo lectura. No participarán en las elecciones de líderes del grupo ni por escrito. Usando Neo4j-streams, podemos transmitir los resultados desde la réplica de lectura al clúster para su consumo.

Las grandes ventajas de abordarlo de esta manera incluyen:

  • Tenemos nuestra alta disponibilidad / recuperación ante desastres que nos brinda el clúster.
  • Los datos serán idénticos tanto en la réplica de lectura como en el clúster. No tenemos que preocuparnos por actualizar la réplica de lectura porque el clúster se encargará de eso por nosotros.
  • Los ID de los nodos y las relaciones serán idénticos tanto en los servidores del clúster como en la réplica de lectura. Esto hace que la actualización sea realmente fácil.
  • Podemos aprovisionar recursos según sea necesario para la réplica de lectura, que probablemente sea muy diferente del clúster.

Nuestra arquitectura se verá como la figura a continuación. A es nuestra réplica de lectura y B es nuestro grupo causal. A recibirá información transaccional de B. Cualquier resultado calculado por A se transmitirá a B a través de mensajes Kafka.

Entonces, con nuestro patrón actualizado, continuemos con nuestro sencillo ejemplo.

El conjunto de datos de ejemplo

Vamos a utilizar el conjunto de datos de la base de datos de películas disponible en: reproducir la guía de la guía de películas en el navegador Neo4j. Para este ejemplo, vamos a utilizar cuatro instancias de Neo4j:

  • La instancia de análisis: esta será nuestra réplica de lectura y, en esta instancia, ejecutaremos PageRank en todos los nodos de Persona del conjunto de datos. Llamaremos al procedimiento streams.publish () para publicar el resultado en nuestro tema de Kafka.
  • Las instancias operativas: este será nuestro clúster causal de tres servidores que escuchará cualquier cambio en el nodo de persona. Actualizaremos a medida que entren los cambios.

Para Kafka, seguiremos las instrucciones desde la guía de inicio rápido hasta el paso 2. Antes de poner en funcionamiento Kafka, necesitaremos configurar los elementos del consumidor en los archivos de configuración de Neo4j. También configuraremos el clúster mismo. Tenga en cuenta que, por el momento, neo4j-streams solo funciona con Neo4j versión 3.4.x.

Para configurar los tres clústeres de servidores y una réplica de lectura, seguiremos las instrucciones proporcionadas en el manual de operaciones de Neo4j. Siga las instrucciones para los núcleos y también para una réplica de lectura.

Además, vamos a necesitar agregar lo siguiente a neo4j.config para los servidores de clúster causales:

# ************
# Kafka Config - Consumidor
# ************
kafka.zookeeper.connect = localhost: 2181
kafka.bootstrap.servers = localhost: 9092
kafka.group.id = neo4j-core1
streams.sink.enabled = true
streams.sink.topic.cypher.neorr = WITH event.payload as payload MATCH (p: Person) WHERE ID (p) = payload [0] SET p.pagerank = payload [1]

Tenga en cuenta que queremos cambiar kafka.group.id a neo4j-core2 y neo4j-core3 respectivamente.

Para la réplica de lectura, necesitaremos agregar lo siguiente a neo4j.config:

# ************
# Kafka Config - Procedimiento
# ************
kafka.zookeeper.connect = localhost: 2181
kafka.bootstrap.servers = localhost: 9092
kafka.group.id = neo4j-read1

Necesitará descargar y guardar el jar neo4j-streams en la carpeta de complementos. También debe agregar la biblioteca de algoritmos gráficos, a través de Neo4j Desktop, o manualmente.

Con estos cambios en los respectivos archivos de configuración configurados y guardados y los complementos instalados, comenzaremos todo, en el siguiente orden:

  • Apache Zookeeper
  • Apache Kafka
  • Las tres instancias para el grupo causal Neo4j
  • La réplica leída

Una vez que todas las instancias de Neo4j estén en funcionamiento y el clúster haya descubierto a todos los miembros, ahora podemos ejecutar la siguiente consulta en la réplica de lectura:

LLAME a algo.pageRank.stream ('MATCH (p: Person) RETURN id (p) AS id',
'COINCIDIR (p1: Persona) -> () <- (p2: Persona) VOLVER ID distinto (p1) COMO fuente, id (p2) COMO objetivo', {gráfico: 'cypher'}) YIELD nodeId, puntaje
WITH [nodeId, score] AS res
LLAMAR streams.publish ('neorr', res)
CUENTA DE DEVOLUCIÓN (*)

Esta consulta de Cypher llamará al algoritmo de PageRank con la configuración especificada. Una vez que se complete el algoritmo, transmitiremos los ID de nodo devueltos y la puntuación de PageRank al tema especificado.

Podemos echar un vistazo a cómo se ve el tema neorr ejecutando el Paso 5 de la guía de inicio rápido de Apache Kafka (reemplazando la prueba con neorr):

Resumen

En esta publicación hemos demostrado:

  • Separar preocupaciones de datos transaccionales y analíticos
  • Resultados analíticos que fluyen indoloramente para el consumo en tiempo real

Si bien hemos usado un ejemplo simple, puede ver cómo se puede llevar a cabo un trabajo analítico complejo, respaldando una arquitectura basada en eventos.