Solución NoSQL para gráficos persistentes a escala

Estoy enganchado al uso de Python y NetworkX para analizar gráficos y, a medida que aprendo, quiero usar más y más datos (supongo que me estoy convirtiendo en un adicto a los datos :-). Finalmente, creo que mi gráfico NetworkX (que se almacena como un dictado) superará la memoria de mi sistema. Sé que probablemente pueda agregar más memoria pero me preguntaba si habría una manera de integrar NetworkX con Hbase o una solución similar.

Miré a mi alrededor y realmente no pude encontrar nada, pero tampoco pude encontrar nada relacionado con permitir un simple backend MySQL.

es posible? ¿Existe algo para permitir la conectividad a algún tipo de almacenamiento persistente?

¡Gracias!

Actualización: recuerdo haber visto este tema en ‘Análisis de redes sociales para empresas emergentes’, el autor habla sobre otros métodos de almacenamiento (incluidos hbase, s3, etc.) pero no muestra cómo hacerlo o si es posible.

Hay dos tipos generales de contenedores para almacenar gráficos:

  1. bases de datos de gráficos reales: por ejemplo, Neo4J , agamemnon , GraphDB y AllegroGraph ; estos no solo almacenan un gráfico sino que también entienden que un gráfico es, así que, por ejemplo, puede consultar estas bases de datos, por ejemplo, ¿cuántos nodos hay entre la ruta más corta del nodo X y el nodo Y ?

  2. Contenedores de gráficos estáticos : el FlockDB adaptado a MySQL de Twitter es el ejemplo más conocido aquí. Estos DB pueden almacenar y recuperar gráficos muy bien; pero para consultar el gráfico en sí, primero debe recuperar el gráfico de la base de datos y luego usar una biblioteca (por ejemplo, la excelente Networkx de Python) para consultar el gráfico en sí.

El contenedor gráfico basado en redis que analizo a continuación se encuentra en la segunda categoría, aunque aparentemente redis también es adecuado para contenedores en la primera categoría, como lo demuestra redis-graph , un paquete de python notablemente pequeño para implementar una base de datos gráfica en redis.

Redis funcionará muy bien aquí.

Redis es un almacén de datos resistente y duradero adecuado para el uso en producción, pero también es lo suficientemente simple para el análisis de línea de comandos.

Redis es diferente de otras bases de datos en que tiene múltiples tipos de estructura de datos; El que recomendaría aquí es el tipo de datos hash . El uso de esta estructura de datos de redis le permite imitar muy de cerca una “lista de diccionarios”, un esquema convencional para almacenar gráficos, en el que cada elemento de la lista es un diccionario de bordes codificados en el nodo desde el cual se originan esos bordes.

Primero debes instalar redis y el cliente de Python. El Blog de DeGizmo tiene un excelente tutorial de “puesta en marcha” que incluye una guía paso a paso para instalar ambos.

Una vez que se hayan instalado redis y su cliente de Python, inicie un servidor de redis , que así lo hace:

  • cd al directorio en el que instaló redis ( / usr / local / bin en ‘nix si lo instaló mediante make install ); siguiente

  • escriba redis-server en el indicador de comandos de shell y luego ingrese

Ahora debería ver el archivo de registro del servidor en su ventana de shell

>>> import numpy as NP >>> import networkx as NX >>> # start a redis client & connect to the server: >>> from redis import StrictRedis as redis >>> r1 = redis(db=1, host="localhost", port=6379) 

En el siguiente fragmento, he almacenado un gráfico de cuatro nodos; Cada línea a continuación llama a hmset en el cliente redis y almacena un nodo y los bordes conectados a ese nodo (“0” => sin borde, “1” => borde). (En la práctica, por supuesto, abstraerá estas llamadas repetitivas en una función; aquí muestro cada llamada porque probablemente sea más fácil de entender de esa manera).

 >>> r1.hmset("n1", {"n1": 0, "n2": 1, "n3": 1, "n4": 1}) True >>> r1.hmset("n2", {"n1": 1, "n2": 0, "n3": 0, "n4": 1}) True >>> r1.hmset("n3", {"n1": 1, "n2": 0, "n3": 0, "n4": 1}) True >>> r1.hmset("n4", {"n1": 0, "n2": 1, "n3": 1, "n4": 1}) True >>> # retrieve the edges for a given node: >>> r1.hgetall("n2") {'n1': '1', 'n2': '0', 'n3': '0', 'n4': '1'} 

Ahora que el gráfico continúa, recupérelo de la base de datos de redis como un gráfico de NetworkX.

Hay muchas maneras de hacerlo, a continuación lo hice en dos * pasos *:

  1. extraiga los datos de la base de datos de redis en una matriz de adyacencia , implementada como una matriz NumPy 2D; entonces

  2. conviértalo directamente a un gráfico de NetworkX usando una función incorporada de NetworkX:

Reducido a código, estos dos pasos son:

 >>> AM = NP.array([map(int, r1.hgetall(node).values()) for node in r1.keys("*")]) >>> # now convert this adjacency matrix back to a networkx graph: >>> G = NX.from_numpy_matrix(am) >>> # verify that G in fact holds the original graph: >>> type(G)  >>> G.nodes() [0, 1, 2, 3] >>> G.edges() [(0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (3, 3)] 

Cuando finaliza una sesión de redis, puede cerrar el servidor desde el cliente de la siguiente manera:

 >>> r1.shutdown() 

redis guarda en el disco justo antes de que se apague, por lo que es una buena manera de garantizar que todas las escrituras se mantuvieron.

Entonces, ¿dónde está el redis DB? Se almacena en la ubicación predeterminada con el nombre de archivo predeterminado, que es dump.rdb en su directorio de inicio.

Para cambiar esto, edite el archivo redis.conf (incluido con la distribución fuente de redis); ir a la línea que comienza con:

 # The filename where to dump the DB dbfilename dump.rdb 

cambie dump.rdb a cualquier cosa que desee, pero deje la extensión .rdb en su lugar.

A continuación, para cambiar la ruta del archivo, busque esta línea en redis.conf:

 # Note that you must specify a directory here, not a file name 

La siguiente línea es la ubicación del directorio para la base de datos de redis. Edítalo para que recite la ubicación que deseas. Guarde sus revisiones y cambie el nombre de este archivo, pero mantenga la extensión .conf. Puede almacenar este archivo de configuración en cualquier lugar que desee, solo proporcione la ruta completa y el nombre de este archivo de configuración personalizado en la misma línea cuando inicie un servidor redis:

Por lo tanto, la próxima vez que inicie un servidor redis, debe hacerlo así (desde el indicador de comandos del shell:

 $> cd /usr/local/bin # or the directory in which you installed redis $> redis-server /path/to/redis.conf 

Finalmente, el Índice de Paquetes de Python enumera un paquete específicamente para implementar una base de datos gráfica en redis. El paquete se llama redis-graph y no lo he usado.

Hay una implementación de NetworkX respaldada por SQLlite3 llamada Cloudlight. https://www.assembla.com/spaces/cloudlight/wiki/Tutorial

Me interesaría ver la mejor manera de usar el disco duro. En el pasado he hecho varios gráficos y los he guardado como archivos .dot. Luego, de alguna manera, mezclé algunos de ellos en la memoria. Aunque no es la mejor solución.

 from random import random import networkx as nx def make_graph(): G=nx.DiGraph() N=10 #make a random graph for i in range(N): for j in range(i): if 4*random()<1: G.add_edge(i,j) nx.write_dot(G,"savedgraph.dot") return G try: G=nx.read_dot("savedgraph.dot") except: G=make_graph() #This will fail if you don't use the same seed but have created the graph in the past. You could use the Singleton design pattern here. print G.adj