用途
面向与 Redis 通信的客户端侧实践指导,帮助开发者高效使用 Redis:如何共享连接、如何批量发送命令、哪些命令不应在生产环境调用、何时开启客户端缓存,以及如何设置超时,在不破坏正常流量的前提下快速失败。
适用时机
- 创建或审查 Redis 客户端配置(redis-py、Jedis、Lettuce、go-redis、NRedisStack)。
- 进行大量小型 Redis 调用,想定位延迟来源。
- 遍历大型 keyspace、集合、哈希或列表。
- 为热键启用客户端缓存。
- 调整连接 / 读 / 写超时。
1. 连接池或连接复用——切勿每请求一连接
Redis 客户端代码中最大的错误是为每个操作都新建一个 TCP 连接。应始终采用以下方式之一:
- 连接池(Pool):保持 N 个持久连接,应用按调用租用(redis-py ConnectionPool、Jedis JedisPooled、go-redis client)。
- 连接复用(Multiplex):所有请求共享单个连接(Lettuce、NRedisStack)。
| 方式 | 使用者 | 说明 |
|---|---|---|
| 连接池 | redis-py、Jedis、go-redis | 池耗尽时每次租用会阻塞;按并发量设置池大小 |
| 连接复用 | Lettuce、NRedisStack | 单连接;无法承载 BLPOP 等阻塞命令 |
# redis-py — 连接池
pool = redis.ConnectionPool(host="localhost", port=6379, max_connections=50)
r = redis.Redis(connection_pool=pool)
更多 Python + Java + Lettuce 示例见 references/pooling.md。
2. 用流水线批量处理
对于 N 个彼此不依赖结果的命令,使用流水线(pipelining)作为单批次发送,将 N 次往返减少为一次。
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. 避免会扫描全部内容的命令
任何遍历整个 keyspace(或整个大型容器)的操作都会阻塞服务端,应改用增量变体。
| 不要使用 | 改用 |
|---|---|
| KEYS pattern | SCAN 游标循环 |
| SMEMBERS large_set | SSCAN |
| HGETALL large_hash | HSCAN |
| 超大列表上的 LRANGE 0 -1 | 分页(LRANGE 0 100) |
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. 为热键启用客户端缓存
对于读取频繁、写入很少的数据(配置、功能开关、每个请求都访问的会话),启用 RESP3 客户端缓存。客户端保留本地副本,服务端在写入时使其失效,从而为热读省去往返。
client = redis.Redis(
host="localhost",
port=6379,
protocol=3, # 需要 RESP3
cache_config=redis.CacheConfig(max_size=1000),
)
对于写入密集的工作负载或持续变化的数据应跳过此设置——失效流量会超过节省的收益。
更多内容见 references/client-cache.md。
5. 设置显式超时
默认值因客户端而异,可能过于宽松。应选择与应用失败模型匹配的值:
r = redis.Redis(
host="localhost",
socket_connect_timeout=2.0, # 对失效节点快速失败
socket_timeout=5.0, # 按预期操作时间调整
retry_on_timeout=True,
)
经验法则:连接超时短于读 / 写超时。对延迟敏感的路径使用紧凑超时 + 超时重试;批处理任务使用更长超时。
更多内容见 references/timeouts.md。
参考
- Redis: Connection Pools and Multiplexing
- Redis: Pipelining
- Redis: SCAN
- Redis: Client-side caching
- Redis: Clients