如何在多线程程序中使用redis-py更高效?

时间:2014-04-29 05:47:41

标签: python multithreading redis

我有两个问题。

  1. 创建一个全局实例并在每个线程中重用或在每个线程中创建一个新实例?

  2. 使用

    pool = redis.ConnectionPool(host ='localhost',port = 6379,db = 0)
     r = redis.Redis(connection_pool = pool)

    r = redis.StrictRedis(host ='localhost',port = 6379,db = 0)

    文档说明了ConnectionPool:You may choose to do this in order to implement client side sharding or have finer grain control of how connections are managed。但我无法理解client side sharing引用的是什么。

  3. 更新
    如果使用ConnectionPool,下面哪条路是对的?
    答:

    pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
    
    class DownloadThread(threading.Thread):
        def __init__(self,pool):
            threading.Thread.__init__(self)
            self.r = redis.Redis(connection_pool=pool)
        def run(self):
            while True:
                self.r .....
    

    B:

    pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
    
    class DownloadThread(threading.Thread):
        def __init__(self,r):
            threading.Thread.__init__(self)
            self.r = r
        def run(self):
            while True:
                self.r .....
    

2 个答案:

答案 0 :(得分:1)

嗯,这里有几个问题,所以我会尝试单独回答。

  1. 如果您要使用线程,那么您当然需要单独的连接。如果共享,Redis连接将不是线程安全的,因为您可以在一个线程上发送请求并且可能在另一个线程上读取(除非您使用互斥锁/锁定)。连接池实现在我看来是线程安全的,所以你应该选择它,或者使用像queue.Queue之类的东西创建你自己的连接池,其中放置各个连接并将线程放到队列中。

  2. 客户端分片是在多个redis实例上分片数据的“穷人”方法。典型的策略包括将某种散列(如crc32)应用于目标键,并获取该值的模数和分片数。一个例子看起来像这样:

  3. -

    >>> binascii.crc32("foo") % 3
    1
    >>> binascii.crc32("bar") % 3
    2
    >>> binascii.crc32("baz") % 3
    0
    

    这假设我们有3个分片(或单个redis服务器实例)。键foo位于第二个分片(索引1)中。密钥bar位于第3个分片(索引2)上,baz位于第1个分片上。

    Redis Cluster(Redis 3.0.0测试版)的目标是在服务器端与客户端进行分片。

答案 1 :(得分:0)

Redis现在是线程安全的:https://github.com/andymccurdy/redis-py

Redis客户端实例可以在线程之间安全地共享。在内部,仅在命令执行期间从连接池中检索连接实例,然后在连接后立即将其返回到池中。命令执行绝不会修改客户端实例上的状态。

每个Redis()实例自动创建连接池