当MGET使用Redis(> 2,000,000个参数)发出大量请求时redis-py,我收到以下套接字错误:
ConnectionError: Error 104 while writing to socket. Connection reset by peer.
Run Code Online (Sandbox Code Playgroud)
我从不同的客户那里尝试过这个,但问题仍然存在.我在这里读到可能存在窗口缩放错误,因此我尝试调整net.ipv4.tcp_wmem并net.ipv4.tcp_rmem使用较小的最大窗口,但这也不起作用.我在Python 2.7.3,Ubuntu 12.04.1 LTS和Redis 2.6.4上运行它.
您无法使用单个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)
Run Code Online (Sandbox Code Playgroud)