2012-02-15 17 views
26

Estoy usando Python y NetworkX para analizar gráficos y, a medida que aprendo más, 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 de NetworkX (que está almacenado como un dict de dict) excederá la memoria en mi sistema. Sé que probablemente solo pueda agregar más memoria, pero me preguntaba si había una forma de integrar NetworkX con Hbase o una solución similar.Solución NoSQL para gráficos persistentes en escala

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

¿Esto 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 startups', el autor habla sobre otros métodos de almacenamiento (incluidos hbase, s3, etc.) pero no muestra cómo hacerlo o si es posible.

+3

edité el título de su pregunta y agregué la etiqueta "nosql". En particular, eliminé la referencia en el título a * networkx * porque networkx no requiere un formato/protocolo de gráfico en particular (de hecho, tiene métodos para traducir desde/a todos los formatos comunes), por lo que el hecho de que sus gráficos sean generado a partir de networkx no tiene influencia sobre las posibles respuestas. – doug

Respuesta

41

Hay dos tipos generales de contenedores para los gráficos de almacenamiento:

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

  2. contenedores de gráfico estático: Twitter's adaptado a MySQL FlockDB es el ejemplo más conocido aquí. Estos DB pueden almacenar y recuperar los gráficos muy bien; pero para consultar el gráfico en sí, primero tiene que recuperar el gráfico de la Base de Datos y luego usar una biblioteca (por ejemplo, el Networkx excelente de Python ) para consultar el gráfico en sí.

El contenedor gráfico basado en redis discutir a continuación se encuentra en la segunda categoría, aunque aparentemente redis está también bien adaptado para contenedores en la primera categoría como se evidencia por redis-graph, una notablemente pequeño paquete de pitón para la aplicación de una gráfica base de datos en redis.

redis funcionará muy bien aquí.

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

Redis es diferente de otras bases de datos ya que tiene múltiples tipos de estructura de datos; el que yo recomendaría aquí es hash tipo de datos.El uso de esta estructura de datos 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 con clave para el nodo desde el que se originan dichos bordes.

Primero debe instalar redis y el cliente de python. El DeGizmo Blog tiene un excelente tutorial "activo" que incluye un guía paso a paso para instalar ambos.

Una vez instalados Redis y su cliente Python, iniciar un servidor Redis, lo que lo hace de esta manera:

  • cd al directorio en el que instaló Redis (/usr/local/bin en 'nix si instaló a través de make install); siguiente tipo

  • Redis-servidor en el intérprete de comandos a continuación, introduzca

Ahora debería ver el archivo de registro del servidor de asimetría 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 de código, 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, sería abstracta estas llamadas repetitivas en una función, aquí estoy mostrando cada llamada, porque lo más probable es 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 se conserva, recuperarlo del Redis DB como un gráfico de NetworkX.

Hay muchas maneras de hacer esto, a continuación lo hizo en dos * pasos *:

  1. extraer los datos de la base de datos Redis en una matriz adyacencia, implementado como un NumPy 2D formación; entonces

  2. convertir ese directamente a un gráfico NetworkX utilizando un NetworkX incorporada función:

reduce al 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) 
     <class 'networkx.classes.graph.Graph'> 
>>> 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 redis, puede cerrar el servidor desde el cliente como lo siguiente:

>>> r1.shutdown() 

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

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

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

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

cambio 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, encontramos esta línea en redis.conf:

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

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

Así que la próxima vez que inicie un servidor redis, debe hacer que como tal (de la línea de comandos:.

$> cd /usr/local/bin # or the directory in which you installed redis 

$> redis-server /path/to/redis.conf 

Finalmente, los Python Package Index listas de un paquete específicamente para la implementación de una base de datos de gráfico en redis el paquete se llama redis-graph y no he utilizado

+1

Wow, muchas gracias. No sabía que esto era posible, pero definitivamente jugaré con eso. Como ha respondido muchas de mis preguntas relacionadas con el gráfico, voy a tratar de elegir su cerebro con otro ... ¿Sabe o ha intentado integrar networkx (o cualquier lib gráfica) con neo4j? Cuando escribí esta pregunta, estaba pensando en redis, pero últimamente parece que neo4j está más optimizado para tareas relacionadas con gráficos ... ¿alguna idea sobre el uso de neo4j con networkx (o jung, etc.)? Necesito estudiar gráficos muy grandes (cientos de millones de nuevos nodos/día) y comparar nodos/hacer pagerank, etc. – Lostsoul

+5

neo4j es una base de datos de gráficos reales; Lo que implementé en mi respuesta es un "gráfico persistente". Ambos pueden almacenar gráficos; un gráfico db "entiende" qué es un gráfico, por lo que se puede consultar como "¿cuántos nodos hay entre nodos X y nodos Y? Para hacer eso en mi implementación de redis anterior, primero debe extraer el gráfico de redis en, por ejemplo, networkx. En otras palabras, neo4j (que es el único gráfico de fuente abierta que conozco) es como mi implementación de redis + una capa de aplicación de gráfico inteligente (networkx). Si prefiere usar Networkx, entonces esa funcionalidad adicional podría simplemente obtener en el camino. – doug

+0

Muchas gracias Doug.Creo que ha respondido a todas las preguntas gráficas que he publicado y me ha enviado cada vez más al interesante mundo de los gráficos. Estoy empezando a ver todos mis problemas como problemas de gráfico, pero algunos de estos conjuntos de datos de problemas pueden ser bastante grandes. Esto no tiene nada que ver con la relación pero, como usted tiene mucha experiencia en este espacio, ¿sabe que el networkx se degrada a medida que los gráficos alcanzan cierto tamaño? Digamos que golpea varios millones de nodos? Estoy haciendo mis propias pruebas, pero un poco en conflicto porque parece que neo4j no asigna de forma nativa. ¿Has golpeado cualquier bloque de carreteras en términos de tamaños de gráfico? – Lostsoul

1

Me interesaría ver la mejor forma de usar el disco duro. En el pasado hice múltiples gráficos y los guardé como archivos .dot. Luego, de algún modo, mezclé algunos de ellos en la memoria. No es la mejor solución sin embargo.

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 
+0

Gracias por la gran respuesta Robert. Pensé en esto, como el peor de los casos, tener un proceso que toma estos archivos planos (que sé cómo crear) y los empuja a Hbase y luego los genera bajo demanda también. No creo que esta sea la mejor respuesta porque a veces la base de datos excede la memoria de almacenamiento del sistema (que en última instancia almacenará estos datos), si hay una forma de hacer que se refiera constantemente a la base de datos que el problema de memoria. – Lostsoul

+0

Sí, espero que alguien publique una mejor respuesta. –

+0

Su respuesta (y proceso de reflexión) es excelente porque al menos hay un plan B en el peor de los casos. No debería ser demasiado difícil enviar archivos al análisis que solo limitan el tamaño de los datos al tamaño de la memoria (pero me gustaría evitar ese trabajo si ya se ha hecho) – Lostsoul

Cuestiones relacionadas