SuperAPI AI 工具集

redis-connections

数据与分析

查看项目

更新于 10-16 10:06

技能介绍

用途

面向与 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