用于大规模保持图的NoSQL解决方案

时间:2012-02-15 22:12:31

标签: python nosql graph-theory networkx

我迷上了使用Python和NetworkX来分析图表,而且我了解更多我想要使用越来越多的数据(猜测我成为了数据迷:-)。最终我认为我的NetworkX图形(存储为dict的dict)将超出我系统的内存。我知道我可能只是添加更多内存,但我想知道是否有办法将NetworkX与Hbase或类似解决方案集成?

我环顾四周,找不到任何东西,但我也找不到与允许简单的MySQL后端相关的任何内容。

这可能吗?是否存在允许连接到某种持久存储的任何内容?

谢谢!

更新:我记得在“初创公司的社交网络分析”中看过这个主题,作者谈到了其他存储方法(包括hbase,s3等等),但没有说明如何执行此操作或如果可能的话。

3 个答案:

答案 0 :(得分:44)

存储图表有两种常规类型的容器:

  1. 真正的图形数据库:例如 Neo4J agamemnon GraphDB AllegroGraph ;这些不仅可以存储图形,而且还可以理解图形,例如,您可以查询这些图形 例如,在最短路径之间有多少个节点 节点X和节点Y

  2. 静态图形容器:Twitter的MySQL改编版FlockDB是这里最知名的范例。这些DB可以存储和检索 图表很好;但要查询图表本身,您必须先行 从数据库中检索图形然后使用库(例如,Python的 优秀的Networkx)来查询图表本身。

  3. 我在下面讨论的基于redis的图形容器属于第二类,但显然redis也非常适合第一类容器,如redis-graph所示,这是一个非常小的用于实现图形的python包redis中的数据库。

    redis 会在这里工作得很漂亮。

    Redis是一个适合生产使用的重型耐用数据存储,但它也足以用于命令行分析。

    Redis与其他数据库的不同之处在于它具有多种数据结构类型;我在这里推荐的是 哈希 数据类型。使用此redis数据结构,您可以非常接近地模仿“字典列表”,这是一种用于存储图形的传统模式,其中列表中的每个项目都是键入这些边缘所源自的节点的边缘字典。

    您需要先安装redis和python客户端。 DeGizmo Blog有一个出色的“正常运行”教程,其中包含一个分步指导安装两者。

    安装redis及其python客户端之后,启动redis服务器,您可以这样做:

    • cd 到您安装redis的目录(如果您通过 make install 安装了 / usr / local / bin ,那么 EM>);下

    • 在shell提示符下键入 redis-server ,然后输入

    您现在应该在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)
    

    在下面的代码段中,我存储了一个四节点图;下面的每一行在redis客户端上调用 hmset 并存储一个节点和连接到该节点的边(“0”=>无边缘,“1”=>边缘)。 (实际上,当然,你会在一个函数中抽象出这些重复的调用;这里我会显示每个调用,因为它可能更容易理解。)

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

    现在图表已保留,请将其作为NetworkX图形从redis DB中检索。

    有很多方法可以做到这一点,下面是两个 *步骤*:

    1. 将redis数据库中的数据提取到邻接矩阵中, 实现为2D NumPy数组;然后

    2. 使用NetworkX将其直接转换为NetworkX图形 内置功能:

    3. 简化为代码,这两个步骤是:

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

      当您结束redis会话时,您可以从客户端关闭服务器,如下所示:

      >>> r1.shutdown()
      

      redis在关闭之前保存到磁盘,因此这是确保所有写入都保持不变的好方法。

      那么redis DB在哪里?它存储在默认位置,使用默认文件名,即主目录中的 dump.rdb

      要更改此设置,请编辑 redis.conf 文件(包含在redis源代码分发中);从以下开始:

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

      将dump.rdb更改为您希望的任何内容,但保留.rdb扩展名。

      接下来,要更改文件路径,请在redis.conf中找到此行:

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

      下面的行是redis数据库的目录位置。编辑它以便它背诵您想要的位置。保存您的修订并重命名此文件,但保留.conf扩展名。您可以将此配置文件存储在任何位置,只需在启动redis服务器时在同一行上提供此自定义配置文件的完整路径和名称:

      因此,下次启动redis服务器时,必须这样做(从shell提示符开始:

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

      最后,Python Package Index列出了专门用于在redis中实现图形数据库的包。该包名为redis-graph,我还没有使用它。

答案 1 :(得分:3)

有一个名为Cloudlight的SQLlite3支持的NetworkX实现。 https://www.assembla.com/spaces/cloudlight/wiki/Tutorial

答案 2 :(得分:1)

我很想看到使用硬盘的最佳方式。在过去,我制作了多个图表并将其保存为.dot文件。然后以某种方式在记忆中混合了一些。虽然不是最好的解决方案。

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