Redis-py连接池重连耗时处理
问题来源
最近项目中用到tornado + mongodb + redis,之前写爬虫的时候用到过redis-py感觉简单容易上手,结合tornado使用就出现了连接池中连接失效重连耗时太久的问题。
代码例子如下:
import time
import redis
redis_setting = dict(
host='127.0.0.1',
)
db = redis.Redis(connection_pool=redis.ConnectionPool(**redis_setting))
def do_with_redis():
now = time.time()
db.get('a')
print(time.time() - now)
def do_something():
do_with_redis() # 第一次查询
time.sleep(301) # do something other,一些业务逻辑
do_with_redis() # 第二次查询
do_something()
-
得到的结果是:
- 第一次查询耗时0.018s左右
- 第二次查询耗时20.018s左右
查看了官方文档说redis连接默认20s超时,关键代码是client.py中669行。
当连接池中的socket已经失效,等待20s s.recv()没有响应,就会抛出异常走到671行,重连继续运行。
解决方案1(不完全)
把连接超时时间缩短,然后超时后断开重连
redis_setting = dict(
host='127.0.0.1',
socket_timeout=1,
socket_connect_timeout=1,
retry_on_timeout=True
)
但是这样还是需要忍受1s的时间
解决方案2(推荐)
让socket连接保持心跳,维持连接状态。找了一堆的socket资料,再读一遍源代码,终于发现还能这样用。
redis_setting = dict(
host='127.0.0.1',
socket_keepalive=True,
socket_keepalive_options={socket.TCP_KEEPIDLE: 60, socket.TCP_KEEPINTVL: 30, socket.TCP_KEEPCNT: 3}
)