使用MGET
向Redis(> 2,000,000个参数)发出大redis-py
个请求时,出现以下套接字错误:
ConnectionError: Error 104 while writing to socket. Connection reset by peer.
我已经尝试过来自不同的客户,但问题仍然存在。我看到here可能存在窗口缩放错误,因此我尝试调整net.ipv4.tcp_wmem
和net.ipv4.tcp_rmem
以获得较小的最大窗口,但这也不起作用。我在Python 2.7.3,Ubuntu 12.04.1 LTS和Redis 2.6.4上运行它。
答案 0 :(得分:6)
您无法使用单个MGET检索此类数量的值。此命令不是为了维持此类工作负载。生成非常大的Redis命令是错误的想法:
在服务器端,所有命令都应该适合输入缓冲区。命令的所有结果都应该适合输出缓冲区。输入缓冲区限制为1 GB。对于输出缓冲区,根据客户端的性质,存在软限制和硬限制。但是将缓冲区增加到接近这些限制的确是在寻找麻烦。当达到限制时,Redis只会关闭连接。
在客户端,可能还有类似的缓冲区和硬编码限制。
Redis是一个单线程事件循环。命令的执行是序列化的。因此,一个非常大的命令将使Redis对所有其他客户端没有响应。
如果您想要检索大量数据,您应该管理多个GET或MGET命令。例如,以下代码可用于检索任意数量的项目,同时最小化往返次数和服务器端CPU消耗:
import redis
N_PIPE = 50 # number of MGET commands per pipeline execution
N_MGET = 20 # number of keys per MGET command
# Return a dictionary from the input array containing the keys
def massive_get( r, array ):
res = {}
pipe = r.pipeline(transaction=False)
i = 0
while i < len(array):
keys = []
for n in range(0,N_PIPE):
k = array[i:i+N_MGET]
keys.append( k )
pipe.mget( k )
i += N_MGET
if i>=len(array):
break
for k,v in zip( keys, pipe.execute() ):
res.update( dict(zip(k,v)) )
return res
# Example: retrieve all keys from 0 to 1022:
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
array = range(0,1023)
print massive_get(r,array)