connectionerror: error 111/10061 表明 redis 服务未启动或未监听指定地址端口,需先检查进程和配置而非重连;broken pipe 等属空闲连接被中间设备回收,应启用健康检查与 tcp keepalive;connectionreplyerror 是服务端明确拒绝,须查配置与日志。

ConnectionError: Error 111 / 10061 是服务没起来,不是重连问题
看到 ConnectionError: Error 111 connecting to 127.0.0.1:6379. Connection refused 或 ConnectionError: Error 10061 connecting to 127.0.0.1:6379. 由于目标计算机积极拒绝,无法连接,第一反应不该是“怎么重连”,而是确认 Redis 进程是否在监听该地址和端口。
这类错误本质是 TCP 层被拒绝(RST 包),说明服务端压根没进程在 127.0.0.1:6379 上 bind() + listen()。自动重试只会让日志刷屏,解决不了根本问题。
- 先用
redis-cli -h 127.0.0.1 -p 6379 ping测试,如果也报错,说明服务未运行或配置了错误的bind地址 - Linux 上执行
sudo ss -tlnp | grep :6379,确认是否有redis-server在监听;Windows 上用netstat -ano | findstr :6379 - 检查
redis.conf:若只留bind 127.0.0.1,远程 Python 就连不上;若要接受外部连接,需注释掉该行或显式写成bind 0.0.0.0(配合protected-mode no) - Ubuntu 虚拟机场景下常见坑:
redis.conf里有三处bind,必须全部注释,否则仍只监听本地回环
ConnectionError: Broken pipe / Connection closed by server 是空闲连接失效
这类错误出现在连接已建立、但后续复用时失败,典型如 Broken pipe、Connection closed by server、周期性集中爆发(比如每 30 秒一批)。根源是中间设备(NAT、防火墙、云厂商 SLB)回收了空闲 TCP 连接,而客户端连接池没感知。
默认的 redis.ConnectionPool 不做健康检查,失效连接会一直留在池里,直到被取出使用时才暴露问题。
- 启用
health_check_interval=30:每 30 秒对空闲连接发PING,失败则自动剔除 - 搭配
retry_on_timeout=True,避免健康检查本身因超时失败而误判 - 设
socket_keepalive=True,并配 Linux 级 TCP keepalive 参数:{socket.TCP_KEEPIDLE: 60, socket.TCP_KEEPINTVL: 30, socket.TCP_KEEPCNT: 3} - 别盲目调高
max_connections;先用INFO clients查看connected_clients和maxclients实际占用,留 20% 余量即可
ConnectionReplyError 不是连接问题,是服务端明确拒绝
ConnectionReplyError 看似像连接异常,实则是 Redis 服务端返回了 ERR 响应,比如 ERR max number of clients reached、ERR invalid password、ERR Client sent AUTH, but no password is set。它和网络层断开无关,重试无效,必须查服务端配置。
- 用
redis-cli -h host -p port -a password ping复现,观察是否报同样ERR - 查 Redis 日志:
tail -f /var/log/redis/redis-server.log,重点关注maxclients、auth、ACL相关提示 - 确认代码中
password、db、username(Redis 6+ ACL)与redis.conf的requirepass、acl-file完全匹配 - 读写分离场景下,避免所有请求共用一个连接池;写节点满载会导致读请求也被卡在池子里,应为不同角色建独立池
重试逻辑必须区分 ConnectionError 和 ResponseError
把所有 Redis 异常都统一重试是危险的。真正该重试的只有网络临时抖动导致的 ConnectionError(如超时、拒绝重试后恢复);而 ConnectionReplyError、ResponseError(如 ERR key doesn't exist)、AuthenticationError 都是语义错误,重试无意义,反而掩盖配置或权限问题。
- 对关键操作(如
r.set()、r.get())捕获redis.ConnectionError后可有限重试(例如 2 次,带指数退避) - 捕获
redis.ResponseError和redis.ConnectionReplyError必须记录完整错误信息并告警,不能静默吞掉 - 设置
socket_connect_timeout=2.0和socket_timeout=3.0,防止单次操作阻塞过久拖垮整个线程 - 连接池初始化时加
decode_responses=True(如需字符串结果),避免后续每次.decode()增加出错点
最易被忽略的是:ConnectionReplyError 看似像连接失败,实则服务端已响应——此时你再怎么调客户端超时、重试、换池子都没用,得立刻去看 redis.conf 和日志。很多团队花半天调 Python 代码,其实改一行配置就恢复了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











