本文介绍在使用缓存数据库 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 结构使用
HGETALL 或 KEYS 命令等。) - 避免在使用 Pipeline 时,单次提交过多的命令(不建议超过 100 条)。
虽然 Pipeline 单次能执行的命令数没有硬限制,但由于 Pipeline 命令会独占 Socket 连接,当命令总数较大时,使用 Pipeline 单次提交过多的命令会影响连接池的分配,也可能出现慢查询。实际上能执行的命令总数,也受限于 Socket 缓冲区和 Redis 请求队列大小,命令越多越容易引起超时或阻塞,从而影响集群稳定性。 - 避免单个 Key 长度超过 128Byte,Value 超过 10KiB。
- 避免
SCAN 、ISCAN 、HSCAN 、SSCAN 、ZSCAN 等命令的限制 COUNT 超过 500。 - 避免
O(N) 命令(例如 LRANGE 、ZRANGE 、SMEMBERS 、SUNION 、SINTER )的单个请求返回值超过 100KiB。 - 避免使用 Lua(EVAL、EVALSHA)脚本。更多关于 Lua 脚本的使用建议,请参见 Lua 脚本使用指南。
- 避免使用 Redis 事务。原因如下:
- Redis 事务没有回滚能力,因此无法保证原子性。
- Redis 事务执行过程中,即使有命令执行报错,也还会把剩下的命令执行完。
|
- 禁止使用“先删缓存,再更新数据库,最后再次延时删除缓存”的缓存双删策略。防止因热点数据的删除出现缓存击穿,甚至数据库宕机问题。
- 禁止使用
KEYS 、FLUSHDB 和 FLUSHALL 等禁用命令。 - 禁止使用
HGETALL 命令(如有遍历需求建议使用 HSCAN 命令)。
|
建议 | - 先更新数据库,再删除缓存。
- 为缓存过期时间增加一个较小的随机值,防止缓存雪崩。
- 单个 Key 长度不超过 44Byte。如果可以,尽量将 Key 的长度控制在 12Byte 以内。
- 将文本类型的 String 数据压缩(推荐使用 GZIP 或 ZSTD 压缩算法)后再存入 Redis。
- 关注热 Key,并适当治理。更多详情,请参见热 Key 分析。
- 关注慢查询。更多详情,请参见查询慢日志。
- 使用 Pipeline 来代替
MGET 、MSET 等需要执行批量操作的命令。
|
- 避免直接对 Hash、Set、Zset 等数据执行
DEL 命令。如有需要,建议使用 HSCAN 、SSCAN 、ZSCAN 等命令进行渐进式删除。 - 避免同一时间(1 秒内)批量删除超过 500 个缓存 Key。
|