连接生命周期
This content is not available in your language yet.
Jedis 的连接是有状态资源:Socket、Redis protocol、认证、数据库选择和 client name 都绑定在连接上。连接复用的前提是归还前状态已经可控。
先给答案:Jedis 的连接是有状态资源:Socket、Redis protocol、认证、数据库选择和 clien…
Section titled “先给答案:Jedis 的连接是有状态资源:Socket、Redis protocol、认证、数据库选择和 clien…”Jedis 的连接是有状态资源:Socket、Redis protocol、认证、数据库选择和 client name 都绑定在连接上。连接复用的前提是归还前状态已经可控。 正文沿“创建与初始化 -> 命令期间 -> 为什么关闭要幂等”展开:先确认入口和状态归属,再跟踪控制流或数据流的推进,最后落到对外可观察的结果。
主要失效边界集中在“连接被阻塞命令占用、借出后未 close、连接异常后继续复用”这些场景。它们破坏的是容量、顺序、并发或生命周期前提;排查时应先确认状态是否仍由正确对象持有,再核对推进条件和清理路径。
创建与初始化
Section titled “创建与初始化”Connection.Builder#build 创建连接后调用初始化逻辑;DefaultJedisSocketFactory 负责 socket、SSL、连接超时和读超时:见 Connection.java:35-120、Connection.java:150-190、DefaultJedisSocketFactory.java:20-120、Connection.java:744-850。
初始化会协商 Redis protocol,随后按配置执行 AUTH、SELECT、CLIENT SETNAME 等命令。配置来源集中在 DefaultJedisClientConfig,避免构造器参数无限增长:见 DefaultJedisClientConfig.java:15-120、DefaultJedisClientConfig.java:242-340、Connection.java:830-919。
Connection#sendCommand 只负责写入,executeCommand 负责写入后读取响应。异常时连接会进入不可复用状态,池工厂随后销毁它,而不是把半断开的 socket 重新交给业务:见 Connection.java:304-373、Connection.java:431-468、ConnectionFactory.java:147-190。
为什么关闭要幂等
Section titled “为什么关闭要幂等”替代方案:由调用方保证只 close 一次。
为什么不行:try-with-resources、池回收、异常清理和显式关闭可能叠加,非幂等 close 会把清理路径变成新的异常源。
证据:Connection#close 先检查 socket/状态,再关闭底层资源;Pool#close 也统一吞并清理异常。
| 场景 | 现象 | 原因 | 规避 |
|---|---|---|---|
| 连接被阻塞命令占用 | 后续命令超时 | 同一连接只能顺序读写 | 独占连接或使用异步/池化策略 |
| 借出后未 close | 池耗尽 | 连接没有归还 | try-with-resources |
| 连接异常后继续复用 | 大量协议错误 | 输入流已失步 | 失败连接直接 destroy |
有状态客户端资源必须把“可复用”作为显式状态,而不是仅凭对象未被 GC 判断;异常路径应优先保证资源不回池。
面试锚点
- Jedis 连接为什么不能并发共享?
- 认证和 SELECT 在何时执行?
- 为什么连接异常后不能简单 reset?