redis-connections
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRedis Connections
Redis 连接
Client-side guidance for talking to Redis efficiently: how to share connections, how to batch commands, which commands not to call in production, when to turn on client-side caching, and how to set timeouts that fail fast without breaking healthy traffic.
客户端高效与Redis通信的指南:如何共享连接、如何批量处理命令、生产环境中不应调用哪些命令、何时开启客户端缓存,以及如何设置快速失败且不影响正常流量的超时时间。
When to apply
适用场景
- Creating or reviewing a Redis client setup (redis-py, Jedis, Lettuce, go-redis, NRedisStack).
- Making many small Redis calls and wondering where the latency is going.
- Iterating large keyspaces, sets, hashes, or lists.
- Enabling client-side caching for hot keys.
- Tuning connect / read / write timeouts.
- 创建或审核Redis客户端配置(redis-py、Jedis、Lettuce、go-redis、NRedisStack)。
- 执行大量小型Redis调用,想排查延迟来源。
- 遍历大型键空间、集合、哈希或列表。
- 为热点键启用客户端缓存。
- 调优连接/读取/写入超时。
1. Pool or multiplex — never one connection per request
1. 使用连接池或多路复用——绝不为每个请求创建一个连接
The single biggest mistake in Redis client code is opening a new TCP connection for every operation. Always either:
- Pool — keep N persistent connections that the application leases per call (redis-py , Jedis
ConnectionPool, go-redis client).JedisPooled - Multiplex — share a single connection across all requests (Lettuce, NRedisStack).
| Style | Used by | Note |
|---|---|---|
| Pool | redis-py, Jedis, go-redis | Each lease blocks if pool exhausted; size the pool to your concurrency |
| Multiplex | Lettuce, NRedisStack | Single connection; cannot carry blocking commands like |
python
undefinedRedis客户端代码中最大的错误就是为每个操作新建一个TCP连接。请始终选择以下两种方式之一:
- 连接池——维护N个持久连接,应用程序每次调用时租赁使用(redis-py 、Jedis
ConnectionPool、go-redis客户端)。JedisPooled - 多路复用——在所有请求间共享单个连接(Lettuce、NRedisStack)。
| 方式 | 适用客户端 | 说明 |
|---|---|---|
| 连接池 | redis-py, Jedis, go-redis | 如果连接池耗尽,每次租赁会阻塞;需根据并发量调整池大小 |
| 多路复用 | Lettuce, NRedisStack | 单个连接;不能执行 |
python
undefinedredis-py — connection pool
redis-py — connection pool
pool = redis.ConnectionPool(host="localhost", port=6379, max_connections=50)
r = redis.Redis(connection_pool=pool)
See [references/pooling.md](references/pooling.md) for Python + Java + Lettuce examples.pool = redis.ConnectionPool(host="localhost", port=6379, max_connections=50)
r = redis.Redis(connection_pool=pool)
查看 [references/pooling.md](references/pooling.md) 获取Python + Java + Lettuce示例。2. Pipeline bulk work
2. 用流水线批量处理任务
For N commands that don't depend on each other's results, send them as a single batch with pipelining. One round-trip instead of N.
python
pipe = redis.pipeline()
for user_id in user_ids:
pipe.get(f"user:{user_id}")
results = pipe.execute()Use non-transactional pipelining for performance, and only when you actually need atomicity (see redis-core's transactions guidance).
pipeline(transaction=True)See references/pipelining.md.
对于彼此不依赖执行结果的N条命令,使用流水线将它们作为单个批次发送。只需一次往返,而非N次。
python
pipe = redis.pipeline()
for user_id in user_ids:
pipe.get(f"user:{user_id}")
results = pipe.execute()为提升性能使用非事务性流水线,仅当确实需要原子性时才使用(参考redis-core的事务指南)。
pipeline(transaction=True)查看 references/pipelining.md。
3. Avoid commands that scan everything
3. 避免全量扫描类命令
Anything that walks the whole keyspace (or a whole large container) blocks the server. Use incremental variants instead.
| Don't | Use |
|---|---|
| |
| |
| |
| Paginate ( |
python
cursor = 0
while True:
cursor, keys = redis.scan(cursor, match="user:*", count=100)
for key in keys:
process(key)
if cursor == 0:
breakBlocking commands (, , ) are different — they intentionally wait for data and are fine for queue consumers, but always pass a timeout, and don't issue them on a multiplexed connection (Lettuce, NRedisStack).
BLPOPBRPOPBLMOVESee references/blocking.md.
任何遍历整个键空间(或大型容器)的命令都会阻塞服务器,请改用增量式变体命令。
| 禁用命令 | 替代命令 |
|---|---|
| |
| |
| |
对超大列表执行 | 分页查询( |
python
cursor = 0
while True:
cursor, keys = redis.scan(cursor, match="user:*", count=100)
for key in keys:
process(key)
if cursor == 0:
break阻塞命令(、、)另当别论——它们会主动等待数据,适合队列消费者使用,但务必设置超时时间,且不要在多路复用连接(Lettuce、NRedisStack)上执行这类命令。
BLPOPBRPOPBLMOVE查看 references/blocking.md。
4. Client-side caching for hot keys
4. 为热点键启用客户端缓存
For data that's read often and written rarely (config, feature flags, sessions on every request), enable RESP3 client-side caching. The client keeps a local copy and the server invalidates it on writes — saving the round trip for hot reads.
python
client = redis.Redis(
host="localhost",
port=6379,
protocol=3, # RESP3 is required
cache_config=redis.CacheConfig(max_size=1000),
)Skip it for write-heavy workloads or data that changes constantly — the invalidation traffic overruns the savings.
See references/client-cache.md.
对于读取频繁、写入极少的数据(配置信息、功能开关、每次请求都需访问的会话数据),启用RESP3客户端缓存。客户端会保留本地副本,服务器在写入时会失效该副本——省去热点数据读取的往返开销。
python
client = redis.Redis(
host="localhost",
port=6379,
protocol=3, # 必须使用RESP3
cache_config=redis.CacheConfig(max_size=1000),
)对于写密集型工作负载或频繁变更的数据,请跳过该配置——失效通知的流量会抵消缓存带来的收益。
查看 references/client-cache.md。
5. Set explicit timeouts
5. 设置明确的超时时间
Defaults vary by client and may be too generous. Pick values that match the application's failure model:
python
r = redis.Redis(
host="localhost",
socket_connect_timeout=2.0, # fail fast on dead nodes
socket_timeout=5.0, # tune to expected operation time
retry_on_timeout=True,
)Rule of thumb: connect timeout shorter than read/write timeout. Tight timeouts + retry-on-timeout for latency-sensitive paths; longer timeouts for batch jobs.
See references/timeouts.md.
不同客户端的默认超时时间差异较大,且可能过于宽松。请选择符合应用故障模型的数值:
python
r = redis.Redis(
host="localhost",
socket_connect_timeout=2.0, # 节点不可用时快速失败
socket_timeout=5.0, # 根据预期操作时长调优
retry_on_timeout=True,
)经验法则:连接超时时间短于读/写超时时间。对延迟敏感的路径使用严格超时+超时重试;批量任务使用更长的超时时间。
查看 references/timeouts.md。