redis-connections

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Redis 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
    ConnectionPool
    , Jedis
    JedisPooled
    , go-redis client).
  • Multiplex — share a single connection across all requests (Lettuce, NRedisStack).
StyleUsed byNote
Poolredis-py, Jedis, go-redisEach lease blocks if pool exhausted; size the pool to your concurrency
MultiplexLettuce, NRedisStackSingle connection; cannot carry blocking commands like
BLPOP
python
undefined
Redis客户端代码中最大的错误就是为每个操作新建一个TCP连接。请始终选择以下两种方式之一:
  • 连接池——维护N个持久连接,应用程序每次调用时租赁使用(redis-py
    ConnectionPool
    、Jedis
    JedisPooled
    、go-redis客户端)。
  • 多路复用——在所有请求间共享单个连接(Lettuce、NRedisStack)。
方式适用客户端说明
连接池redis-py, Jedis, go-redis如果连接池耗尽,每次租赁会阻塞;需根据并发量调整池大小
多路复用Lettuce, NRedisStack单个连接;不能执行
BLPOP
这类阻塞命令
python
undefined

redis-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
pipeline(transaction=True)
only when you actually need atomicity (see redis-core's transactions guidance).
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()
为提升性能使用非事务性流水线,仅当确实需要原子性时才使用
pipeline(transaction=True)
(参考redis-core的事务指南)。
查看 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'tUse
KEYS pattern
SCAN
cursor loop
SMEMBERS large_set
SSCAN
HGETALL large_hash
HSCAN
LRANGE 0 -1
on a huge list
Paginate (
LRANGE 0 100
)
python
cursor = 0
while True:
    cursor, keys = redis.scan(cursor, match="user:*", count=100)
    for key in keys:
        process(key)
    if cursor == 0:
        break
Blocking commands (
BLPOP
,
BRPOP
,
BLMOVE
) 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).
See references/blocking.md.
任何遍历整个键空间(或大型容器)的命令都会阻塞服务器,请改用增量式变体命令。
禁用命令替代命令
KEYS pattern
SCAN
游标循环
SMEMBERS large_set
SSCAN
HGETALL large_hash
HSCAN
对超大列表执行
LRANGE 0 -1
分页查询(
LRANGE 0 100
python
cursor = 0
while True:
    cursor, keys = redis.scan(cursor, match="user:*", count=100)
    for key in keys:
        process(key)
    if cursor == 0:
        break
阻塞命令(
BLPOP
BRPOP
BLMOVE
)另当别论
——它们会主动等待数据,适合队列消费者使用,但务必设置超时时间,且不要在多路复用连接(Lettuce、NRedisStack)上执行这类命令。
查看 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

References

参考资料