如何有效地向Redis插入数十亿的数据?

时间:2015-08-21 21:37:07

标签: python redis redis-py

批量插入到redis服务器

我有大约20亿的键值对,我想有效地将​​它们加载到redis上。我当前正在使用python并使用了redis-py记录的Pipe,但是我无法找到加载到redis上的任何加速

我有以下代码加载到python中的redis

import redis
def load(pdtDict):
    redIs = redis.Redis()
    pipe = redIs.pipeline()
    for key in pdtDict.keys():
        pipe.hmset(self.seller+":"+str(key),pdtDict[key])
    pipe.execute()

其中pdtDict包含要存储在redis上的键值对的字典

任何想法或帮助???

5 个答案:

答案 0 :(得分:5)

关于问题和示例代码的几点。

  1. 流水线不是灵丹妙药 - 您需要在使用之前了解它的作用。流水线操作的作用是批量发送作为批量发送的多个操作,以及它们从服务器发出的响应。您获得的是每个操作的网络往返时间由批次的网络往返时间替换。但无限大小的批次是资源的真正消耗 - 你需要保持它们的大小足够有效。根据经验,我通常会尝试以每个管道60KB为目标,并且由于每个数据都不同,管道中的实际操作数也是如此。假设您的密钥及其值大约为1KB,则需要每60次操作调用pipeline.execute()

  2. 除非我严重误解,否则此代码不应运行。您正在使用HMSET,就好像它是SET一样,因此您基本上缺少Hashes的field->值映射。哈希值(HMSET)和字符串(SET)是不同的数据类型,因此应该相应使用。

  3. 似乎这个小循环负责整个“十亿数据” - 如果是这样的话,不仅运行代码的服务器会像疯了一样交换,除非它有很多RAM保存字典,它也会非常无效(无论Python的速度如何)。您需要通过运行此过程的多个实例来并行化数据插入。

  4. 您是否远程连接到Redis?如果是这样,网络可能会限制您的表现。

  5. 考虑你的Redis设置 - 假设它确实是一个瓶颈,也许可以调整/调整这些设置以获得更好的性能。

答案 1 :(得分:2)

我希望您也在redis python包旁边安装了hiredis python包。请参阅https://github.com/andymccurdy/redis-py#parsers它也应该会提升性能。

self.seller做了什么?也许这是一个瓶颈?

正如@Itamar所说,尝试定期执行管道

def load(pdtDict):
    redIs = redis.Redis()
    pipe = redIs.pipeline()
    n = 1
    for key in pdtDict.keys():
        pipe.hmset(self.seller+":"+str(key),pdtDict[key])
        n = n + 1
        if (n % 64) == 0:
            pipe.execute()
            pipe = redIs.pipeline()

答案 2 :(得分:0)

要向Redis提供大量数据,请考虑使用here所述的redis大量插入功能。

为此,您需要访问redis-cli。

答案 3 :(得分:0)

您可以在管道模式下使用redis-cli,首先准备一个类似的文件(请注意,这些行应以cr / lf终止,或由-d <dilimiter>选项设置):

SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN

然后将其传输到redis-cli:

cat data.txt | redis-cli --pipe

https://redis.io/topics/mass-insert

答案 4 :(得分:0)

另一个考虑因素是,如果满足以下条件(来自Redis Labs),则在管道构造中设置<figure> <img src="{{ include.url }}" alt="{{ include.description }}"> <figcaption>Photo by <a href="{{ include.authorurl }}">{{ include.author }}</a></figcaption> </figure> 有助于提高性能:

  

对于需要向Redis发送多个命令的情况,   一个命令的结果不会影响到另一个命令的输入,我们   不需要它们全部以事务方式执行,只需将False传递给   pipeline()方法可以进一步提高整体Redis性能。