一、一、关注 O(N) 命令中的 N
hgetall、lrange、smembers、zrange、sinter 等命令的时间复杂度为 O(N),使用时需要明确 N 的值。当 N 较大时,这些命令会长时间占用单线程,阻塞其他请求。
| 命令 | 风险说明 | 替代方案 |
| HGETALL | 一次性返回哈希表所有字段,Key 内字段过多时阻塞严重 | 使用 HSCAN 游标分批遍历 |
| SMEMBERS | 一次性返回集合所有成员 | 使用 SSCAN 游标分批遍历 |
| ZRANGE | 一次性返回有序集合指定范围的所有成员 | 使用 ZSCAN 游标分批遍历或缩小查询范围 |
| LRANGE | 一次性返回列表指定范围的所有元素 | 缩小范围或分页获取 |
| SINTER | 多个集合求交集,元素越多耗时越长 | 在业务侧进行交集运算 |
注意:说明:
注意:使用 HSCAN、SSCAN、ZSCAN 命令时,建议指定合适的 COUNT 参数,每次遍历返回1000个元素左右是比较合适的选择。具体数量需根据实例配置和业务场景调整。
二、二、禁用命令
以下命令在生产环境中禁止或限制使用。Redis 基于单线程工作,这些命令执行时间过长或操作风险过高,容易导致命令执行阻塞或数据丢失。建议通过参数 disable-command-list 配置禁用。
| 命令 | 风险说明 | 替代方案 |
| KEYS | 遍历所有键匹配模式,阻塞 Redis 服务器 | 使用 SCAN 游标渐进式匹配 |
| FLUSHDB | 清空当前数据库所有数据,不可恢复 | 通过 SCAN + DEL 渐进式删除 |
| FLUSHALL | 清空实例所有数据库的全部数据,不可恢复 | 通过 SCAN + DEL 渐进式删除 |
| SHUTDOWN | 关闭 Redis 服务器,导致服务中断和数据丢失 | 通过控制台管理实例生命周期 |
| CONFIG | 修改服务器运行时配置,操作不当可能导致崩溃 | 通过控制台修改实例参数 |
以下命令不建议在生产环境频繁使用:
| 命令 | 风险说明 | 使用建议 |
| RANDOMKEY | 随机返回一个键,会阻塞 Redis 服务器 | 仅在测试环境使用 |
| INFO | 返回服务器统计信息,执行过程中阻塞其他请求 | 仅在问题排查时短时使用 |
| BGREWRITEAOF | 异步重写 AOF 文件,消耗大量系统资源 | 由系统自动触发,避免手动执行 |
| BGSAVE | 异步生成 RDB 快照,消耗大量系统资源 | 由系统自动触发,避免手动执行 |
注意:说明:
注意:在运维场景中,如确需使用 INFO 或 CONFIG 命令进行排查,应在低峰期短时操作,操作完毕后及时退出。
三、三、合理使用 Select
Redis 支持多数据库(Multi-DB),数据库索引号以0作为起始索引值,可通过 SELECT 命令随时切换。
| 架构 | 使用建议 |
| 标准版 | 可根据多 DB 进行数据区分,但 Redis 本身基于单线程处理,多 DB 之间的请求会相互影响 |
| 集群版 | 建议优先使用0号 DB,非 0 DB 不支持扩容 |
注意:说明:
注意:在集群版场景中,客户端请求0号 DB 时可以不执行 SELECT 0,减少非必要的网络交互。
四、四、适当使用批量操作
应用侧访问 Redis 时,较大一部分耗时来自网络 RTT。如果需要执行大量的 GET 或 SET 操作,可以使用批量命令降低网络开销。
| 方式 | 说明 | 适用场景 |
| 原生批量命令(MGET/MSET) | 原子操作,服务端一次性执行 | 批量读写同类型的 Key |
| Pipeline | 非原子操作,客户端将多条命令打包发送 | 批量执行不同类型的命令 |
反面示例: 单次批量操作元素个数超过500,导致单次请求耗时过长,后端抖动或扩容时对业务影响较大。
MGET key1 key2 key3 … key1000
正确示例: 将批量操作拆分为多次,每次控制在500个元素以内。
# 第一批MGET key1 key2 … key500# 第二批MGET key501 key502 … key800
注意:说明:
五、五、不建议使用事务
Redis 的事务功能较弱,不支持回滚。在集群版场景中,一次事务操作的 Key 必须在同一个 Slot 上,否则事务执行将失败。
注意:说明:
注意:如果业务需要事务性保障,建议使用 Lua 脚本替代。Lua 脚本在服务端原子执行,但同样要求集群版中所有操作的 Key 位于同一个节点上。
六、6.1 Key 必须通过 KEYS 数组传递
redis.call / redis.pcall 中调用的 Redis 命令,Key 的位置必须来自 KEYS 数组,否则返回错误:
-ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array
七、6.2 操作的 Key 必须在同一个节点
单个 Lua 脚本操作的 Key 必须在同一个节点上,否则返回错误:
Lua script attempted to access a non local key in a cluster node
注意:说明:
注意:如需在 Lua 脚本中操作多个 Key,可通过 Hashtag 将相关 Key 分配到同一个哈希槽中。使用前请参见这篇第八节 Hashtag 的使用建议。
八、七、关于 Monitor 命令
Monitor 命令用于实时输出 Redis 服务器接收到的命令流,对服务器性能有一定影响。
| 场景 | 使用建议 |
| 日常运行 | 不建议开启 Monitor |
| 问题排查 | 可短时开启用于分析命令执行情况,排查完毕后及时关闭 |
注意:说明:
注意:长时间开启 Monitor 会持续消耗服务器资源并占用输出缓冲区,导致性能下降。如无排查需求,请勿开启。
九、八、使用 Hashtag 建议
Hashtag 是 Redis 集群提供的一种特殊规则,用于通过特定语法强制将多个不同的键分配至同一个哈希槽(Hash Slot),以支持跨键操作。如使用不当,将导致严重的数据与请求倾斜问题,且该问题无法通过集群扩容解决。
十、8.1 Hashtag 使用不当的风险
| 风险类型 | 说明 |
| 数据倾斜(Memory Skew) | 大量使用相同 Hashtag 的键聚集在某一个节点上,导致该节点内存使用率远高于其他节点,可能提前触发内存告警或写满 |
| 请求倾斜(Hotspot) | 所有针对这些数据的读写请求命中同一个节点,使其成为性能瓶颈,导致延迟增加甚至拖垮整个集群 |
| 不可扩容性 | 哈希槽的计算依赖固定的 Hashtag,由此引发的倾斜问题无法通过增加集群节点来缓解 |
十一、8.2 Hashtag 使用准则
| 准则 | 说明 |
| 最小化与拆分 | 不要为所有关联数据使用一个统一的 Hashtag,应按业务类型或功能模块使用不同的细粒度 Hashtag |
| 保证均匀分布 | 确保 Hashtag 值在整体上均匀分布,可在原始 ID 后添加后缀进行人工分片 |
| 仅在必要时使用 | 仅在必须使用事务、Lua 脚本或多键命令时才使用 Hashtag,无关的键不要滥用此特性 |
反面示例: 所有用户数据使用统一的 Hashtag,导致全部数据聚集在单一节点。
SET {global}:user:1001 "data1"SET {global}:user:1002 "data2"SET {global}:order:5001 "order_data"
正确示例: 按业务类型拆分 Hashtag,数据分散在不同节点。
SET {user:1001}:profile "data1"SET {user:1001}:session "session_data"SET {order:5001}:detail "order_data"
注意:说明:
注意:建议在系统设计阶段评审 Hashtag 的使用方案,上线后再调整需要对存量数据进行迁移,成本较高。
十二、九、禁止将 Redis 作为消息队列
禁止将 Redis 当作消息队列使用。Redis 的发布/订阅和 List 结构不具备消息队列的核心能力,在容量、网络、效率和功能方面存在多种限制。
| 限制项 | 说明 |
| 消息持久化 | Redis 的 Pub/Sub 不持久化消息,消费者离线期间的消息将丢失 |
| 消息确认 | 不支持消费确认机制(ACK),无法保证消息被可靠消费 |
| 堆积能力 | List 结构作为队列时,消息堆积会大量占用内存,影响缓存性能 |
| 消费模型 | 不支持消费者组、消息分区等高级特性 |
注意:说明:
注意:如有消息队列需求,建议使用专业的消息中间件,例如 CKafka 或 TDMQ。