如何在多线程程序中更高效地使用redis-py?
我有两个问题想问。
是创建一个全局的实例,然后在每个线程中重复使用,还是在每个线程中创建一个新的实例?
使用
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)还是
r = redis.StrictRedis(host='localhost', port=6379, db=0)
文档中提到关于连接池的内容:
你可以选择这样做,以便实现客户端分片或更细粒度地控制连接的管理
。但我不太明白这里的客户端分片
指的是什么。
更新
如果使用连接池,下面哪种方式是正确的?
A:
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 个回答
好吧,这里有几个问题,我会分别回答每一个。
如果你打算使用线程,那么你肯定需要每个线程都有自己的连接。因为如果多个线程共享同一个Redis连接,就会出现问题,比如一个线程在发送请求,而另一个线程在读取数据,这样就可能会出错(除非你使用互斥锁来控制)。我觉得连接池的实现是线程安全的,所以你应该选择使用连接池,或者自己创建一个连接池,可以用像queue.Queue这样的东西,把每个连接放进去,线程就可以从队列中取出和放入连接。
客户端分片是一种“穷人的”方式,用来在多个Redis实例上分散数据。通常的做法是对目标键应用某种哈希算法,比如crc32,然后用这个值对分片的数量取模。举个例子,可能会像这样:
--
>>> binascii.crc32("foo") % 3
1
>>> binascii.crc32("bar") % 3
2
>>> binascii.crc32("baz") % 3
0
这里假设我们有3个分片(或者说是3个独立的Redis服务器实例)。键foo
在第二个分片(索引1)上,键bar
在第三个分片(索引2)上,而baz
则在第一个分片上。
Redis集群(在Redis 3.0.0的测试版中)旨在实现服务器端的分片,而不是客户端的分片。
Redis现在是线程安全的:https://github.com/andymccurdy/redis-py
Redis的客户端实例可以在多个线程之间安全地共享。内部在执行命令时,连接实例只会从连接池中获取,执行完后又直接放回连接池。执行命令的过程不会改变客户端实例的状态。
每个Redis()实例会自动创建一个连接池。