2012-02-15 8 views
26

Sono appassionato di Python e NetworkX per l'analisi di grafici e, man mano che imparo di più, voglio utilizzare sempre più dati (suppongo di diventare un drogato di dati :-). Alla fine penso che il mio grafico NetworkX (che è memorizzato come un dettato di dict) supererà la memoria sul mio sistema. So che probabilmente posso aggiungere solo più memoria, ma mi chiedevo se c'era un modo per integrare invece NetworkX con Hbase o una soluzione simile?Soluzione NoSQL per grafici persistenti in scala

Mi sono guardato intorno e non riuscivo a trovare nulla ma non sono riuscito a trovare nulla relativo a consentire un semplice back-end MySQL.

È possibile? Esiste qualcosa per consentire la connettività a qualche tipo di archiviazione persistente?

Grazie!

Aggiornamento: Ricordo di aver visto questo argomento in 'Analisi della rete sociale per le startup', l'autore parla di altri metodi di archiviazione (inclusi hbase, s3, ecc.) Ma non mostra come farlo o se è possibile.

+3

ho modificato il titolo della domanda e aggiunto il tag "nosql". In particolare, ho rimosso il riferimento nel titolo in * networkx * perché networkx non richiede un particolare formato/protocollo grafico (infatti, ha metodi per la traduzione da/verso tutti i formati comuni), quindi il fatto che i tuoi grafici sono generato da networkx non ha alcuna influenza sulle possibili risposte. – doug

risposta

41

Ci sono due tipi generali di contenitori per i grafici memorizzazione:

  1. veri database del grafico: esempio, Neo4j, agamemnon, GraphDB e AllegroGraph; questi non solo memorizzano un grafico ma capiscono anche che è un grafico, quindi, per esempio, puoi interrogare questi database ad es., quanti nodi ci sono tra il percorso più breve dal nodo X e il nodo Y?

  2. contenitori per grafici statici: FlockDB adattato da MySQL di Twitter è l'esempio più conosciuto qui. Questi DB possono archiviare e recuperare i grafici bene; ma per interrogare il grafico stesso, è necessario prima il recuperare il grafico dal DB quindi utilizzare una libreria (ad esempio, il Networkx eccellente di Python per interrogare il grafico stesso.

Il contenitore grafico redis basati i discutere qui sotto è nella seconda categoria, anche se apparentemente redis è adatto anche per contenitori nella prima categoria come evidenziato da redis-graph, un'unità di dimensioni ridotte pitone per implementare un grafico database in redis.

redis funzionerà magnificamente qui.

Redis è un data store robusto e duraturo adatto per l'uso di produzione, ma è anche abbastanza semplice da utilizzare per l'analisi da riga di comando.

Redis è diverso da altri database in quanto ha più tipi di strutture di dati; quello che raccomanderei qui è il tipo di dati hash.L'utilizzo di questa struttura dati redis consente di simulare molto attentamente un "elenco di dizionari", uno schema convenzionale per la memorizzazione di grafici, in cui ogni elemento nell'elenco è un dizionario di bordi associati al nodo da cui provengono i bordi.

È necessario prima installare redis e il client python. Il DeGizmo Blog ha un eccellente tutorial "up-and-running" che include un step-by-step guid sull'installazione di entrambi.

Una volta che sono installati Redis e il suo client di pitone, avviare un server Redis, che si fa in questo modo:

  • cd alla directory in cui è stato installato Redis (/usr/local/bin su 'nix se installato tramite make install); prossimo

  • tipo Redis-server al prompt della shell quindi immettere

si dovrebbe ora vedere il file di log del server tailing sulla vostra finestra di 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) 

Nel frammento di seguito, ho memorizzato un grafico a quattro nodi; ogni riga sotto chiama hmset sul client redis e memorizza un nodo e gli spigoli connessi a quel nodo ("0" => nessun bordo, "1" => bordo). (In pratica, naturalmente, si sarebbe astratta queste chiamate ripetitive in una funzione; qui sto mostrando ogni chiamata perché è più probabile che più facile da capire in questo modo.)

>>> 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'} 

Ora che il grafico viene mantenuto, recuperarla dal redis DB come un grafico NetworkX.

Ci sono molti modi per farlo, di seguito ha fatto in due * passi *:

  1. estrarre i dati dal database Redis in una matrice adiacenze, implementato come NumPy 2D matrice; poi

  2. convertito che direttamente ad un grafico NetworkX utilizzando un NetworkX incorporata funzione:

ridotto al codice queste due fasi sono:

>>> 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)] 

Quando si finisce una sessione redis, è possibile arrestare il server dal client in questo modo:

>>> r1.shutdown() 

redis salva su disco appena prima che si chiuda, quindi questo è un buon modo per garantire che tutte le scritture siano state mantenute.

Quindi, dov'è il DB redis? È archiviato nella posizione predefinita con il nome file predefinito, ovvero dump.rdb sulla tua home directory.

per cambiare questo, modificare il redis.conf file di (incluso con la sorgente di Redis distribuzione); passare alla riga che inizia con:

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

cambiamento dump.rdb a tutto ciò che si desidera, ma lasciare l'estensione .rdb a posto.

Avanti, per modificare il percorso del file, trovare questa linea in redis.conf:

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

La linea sotto che è il percorso di directory per il database Redis. Modificalo in modo che reciti la posizione che desideri. Salva le tue revisioni e rinomina questo file, ma mantieni l'estensione .conf. È possibile memorizzare questo file di configurazione ovunque si desideri, basta fornire il percorso completo e il nome di questo file di configurazione personalizzato sulla stessa riga quando si avvia un server redis:

Quindi la prossima volta che si avvia un server redis, è necessario eseguire in questa maniera (dalla shell:.

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

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

Infine, i Python Package Index elenchi un pacchetto specifico per l'implementazione di un database grafico in redis il pacchetto è chiamato redis-graph e non ho usato

+1

Wow, grazie mille. Non sapevo che fosse possibile, ma mi piacerebbe giocarci. Dato che hai risposto molte delle mie domande relative al grafico, cercherò di scegliere il tuo cervello con un altro. Sai o hai provato ad integrare networkx (o qualsiasi lib di grafica) con neo4j? Quando ho scritto questa domanda stavo pensando ai redis, ma ultimamente sembra che neo4j sia più ottimizzato per le attività relative ai grafi ... tutti i pensieri sull'uso di neo4j con networkx (o jung, ecc.)? Ho bisogno di studiare grafici molto grandi (centinaia di milioni di nuovi nodi/giorno) e confrontare i nodi/fare il pagerank, ecc. – Lostsoul

+5

neo4j è un vero database di grafici; ciò che ho implementato nella mia risposta è un "grafico persistente". Entrambi possono memorizzare grafici; un grafico db "capisce" cos'è un grafico, quindi può essere interrogato come "quanti nodi sono tra i nodi X e i nodi Y? Per farlo nell'implementazione di redis di cui sopra è necessario prima estrarre il grafico da redis ad esempio, networkx. In altre parole, neo4j (che è l'unico grafico open source db che conosca) è come la mia implementazione redis + un livello di applicazione di grafi smart (networkx) .Se preferisci usare Networkx, allora questa funzionalità aggiuntiva potrebbe nel modo. – doug

+0

Grazie mille Doug.Penso che tu abbia risposto ad ogni domanda sul grafico che ho postato e mi abbia inviato sempre più in profondità nell'interessante mondo dei grafici. Sto iniziando a vedere tutti i miei problemi come problemi di grafici ma alcuni di questi problemi possono diventare piuttosto grandi. Questa è una specie di non correlato ma, come i tuoi esperti in questo spazio, sai che Networkx degrada quando i grafici raggiungono una certa dimensione? Dite che colpisce diversi miliardi di nodi? Sto facendo i miei test, ma un po 'in conflitto perché neo4j sembra fare assegnamento in modo nativo. Hai colpito blocchi stradali in termini di dimensioni del grafico? – Lostsoul

1

Sarei interessato a vedere il modo migliore di utilizzare il disco rigido. In passato ho creato più grafici e li ho salvati come file .dot. Quindi in qualche modo li ha mixati alcuni in memoria. Non è la soluzione migliore però.

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

Grazie per l'ottima risposta Robert. Ho pensato a questo, nel peggiore dei casi, di avere un processo che prende questi file flat (che so come creare) e li spinge a Hbase e poi li genera anche su richiesta. Non penso che questa sia la migliore risposta perché a volte il database supera la memoria di archiviazione dei sistemi (che alla fine memorizzerà questi dati come), se c'è un modo per fare riferimento costantemente al database che il problema di memoria non c'è più. – Lostsoul

+0

Sì, spero che qualcuno pubblichi una risposta migliore. –

+0

La tua risposta (e la tua riflessione) è ottima perché almeno nel caso peggiore c'è un piano B. Non dovrebbe essere troppo difficile inviare file ad analisi che limitano solo la dimensione dei dati alla dimensione della memoria (ma vorrei evitare che funzioni se è già stato fatto) – Lostsoul