You need to enable JavaScript to run this app.
导航

业务代码开发建议

最近更新时间2024.02.06 15:36:37

首次发布时间2022.10.17 21:23:46

本文介绍在使用缓存数据库 Redis 版进行业务代码开发时,需要注意的使用建议。

建议级别说明

强烈建议

  • 将 Redis 仅作为缓存使用。原因在于 Redis 的持久化和主从复制都是异步进行的,不太适用于对数据可靠性和一致性要求较高的场景。
  • 设置缓存过期时间。
  • 对服务端超时等错误信息进行监控,并设置客户端重试机制来应对限流或主备切换等场景。
  • 设置 Redis 实例的监控告警,监控对象包括内存使用率、CPU 使用率等。更多详情,请参见监控告警
  • 密切关注大 Key 相关指标(如单个响应的最大字节数)并及时治理。更多详情,请参见大 Key 分析
  • 开启客户端 SDK 的连接池功能,避免使用单个连接,并设置重连机制。具体原因如下:
    • 使用单个连接的情况下,如果前面有一个慢请求,将导致后续请求出现等待,获取空闲连接耗时较长;如果该连接被断开,也会影响较多请求。
    • 您可以参考如下方式来计算客户端 SDK 连接池所需连接数:
      所需连接数 = 期望达成的 QPS ÷ 单个连接的 QPS。
      其中单个连接的 QPS 可以通过 1 秒内单次请求的平均耗时来计算。例如客户端平均每个请求耗时 1ms,那单个连接能达成的 QPS 就是 1000,如果期望单个客户端能够达到 2 万 QPS,则可以设置 20 个连接,通常建议可以预留一些冗余量,例如设置 30 个连接。
    • 当数据库中 Key 数量较多时(如超过了 100 万个),建议开启客户端的负载均衡功能。
  • 设置宽松的超时重试时间(例如 200 毫秒以上),避免超时引起的重试风暴。
  • 避免不同业务混用 Redis 实例。
  • 避免在 Hash、Set、Zset 等数据结构中存放过多子 Key(子 Key 数量不建议超过 1000 个)。
  • 避免单条命令操作过多的数据。例如,对元素较多的 Hash 结构使用 HGRTALLKEYS 命令等。)
  • 避免在使用 Pipeline 时,单次提交过多的命令(不建议超过 100 条)。
    虽然 Pipeline 单次能执行的命令数没有硬限制,但由于 Pipeline 命令会独占 Socket 连接,当命令总数较大时,使用 Pipeline 单次提交过多的命令会影响连接池的分配,也可能出现慢查询。实际上能执行的命令总数,也受限于 Socket 缓冲区和 Redis 请求队列大小,命令越多越容易引起超时或阻塞,从而影响集群稳定性。
  • 避免单个 Key 长度超过 128Byte,Value 超过 10KiB。
  • 避免 SCANISCANHSCANSSCANZSCAN 等命令的限制 COUNT 超过 500。
  • 避免 O(N) 命令(例如 LRANGEZRANGESMEMBERSSUNIONSINTER)的单个请求返回值超过 100KiB。
  • 避免使用 Lua(EVAL、EVALSHA)脚本。更多关于 Lua 脚本的使用建议,请参见 Lua 脚本使用指南
  • 避免使用 Redis 事务。原因如下:
    • Redis 事务没有回滚能力,因此无法保证原子性。
    • Redis 事务执行过程中,即使有命令执行报错,也还会把剩下的命令执行完。
  • 禁止使用“先删缓存,再更新数据库,最后再次延时删除缓存”的缓存双删策略。防止因热点数据的删除出现缓存击穿,甚至数据库宕机问题。
  • 禁止使用 KEYSFLUSHDBFLUSHALL 等禁用命令。
  • 禁止使用 HGETALL 命令(如有遍历需求建议使用 HSCAN 命令)。

建议

  • 先更新数据库,再删除缓存。
  • 为缓存过期时间增加一个较小的随机值,防止缓存雪崩。
  • 单个 Key 长度不超过 44Byte。如果可以,尽量将 Key 的长度控制在 12Byte 以内。
  • 将文本类型的 String 数据压缩(推荐使用 GZIP 或 ZSTD 压缩算法)后再存入 Redis。
  • 关注热 Key,并适当治理。更多详情,请参见热 Key 分析
  • 关注慢查询。更多详情,请参见查询慢日志
  • 使用 Pipeline 来代替 MGETMSET 等需要执行批量操作的命令。
  • 避免直接对 Hash、Set、Zset 等数据执行 DEL 命令。如有需要,建议使用 HSCANSSCANZSCAN 等命令进行渐进式删除。
  • 避免同一时间(1 秒内)批量删除超过 500 个缓存 Key。