BigKey 指单个 Key 的 Value 很大或容器元素过多,HotKey 指访问特别频繁。二者可以同时发生,但并不等价。没有适合所有业务的固定字节阈值,应结合单次访问延迟、网络带宽、内存成本和命令复杂度判断。
主要风险在哪里?
大 String 读取需要复制、序列化与传输大量字节;巨大 Hash/List/Set/ZSet 做全量遍历、复杂操作或删除时,可能长时间占用执行线程。复制、迁移和持久化也要处理大对象,带来缓冲增长、迁移抖动或内存峰值。Cluster 把一个 Key 放在一个槽位,增加节点并不会自动拆分这个 Value。
例如把所有用户放进一个 Hash,每次 HGETALL 获取全部数据,即使 Redis 使用哈希表,也需要遍历和返回整个容器。平均 O(1) 的单字段访问不能证明 HGETALL 也很快。
如何发现?
可以用 redis-cli --bigkeys 辅助扫描,并结合 STRLEN、HLEN、LLEN、SCARD、ZCARD 判断规模,用 MEMORY USAGE 估算内存。工具对不同类型的计量方式不同,元素数不等于字节数;采样与扫描也会增加实例负载,生产环境应限速、避开高峰,并遍历 Cluster 的各个相关节点。
如何治理?
按业务维度拆分容器,限制单对象大小,避免全量返回,使用分页或增量访问。拆分同时要考虑原子性、查询次数和热点分布,不能为了“每个 Key 小”把一次操作变成几万次网络请求。
删除大对象可考虑 UNLINK,或按类型分批移除元素;逻辑删除后再异步清理也可减少请求等待。操作前检查来源和业务影响,控制清理速度,避免删除与缓存重建同时把数据库压满。
常见追问
BigKey 一定是 HotKey 吗?
不是。很大的冷数据也会增加内存和持久化成本;很小的热门计数器也能压满单节点 CPU。
UNLINK 能消除所有延迟吗?
不能。它减少某些释放工作对主线程的影响,但后台释放仍耗 CPU 和内存;其他大对象读取、复制和迁移成本仍存在。
给 BigKey 加 TTL 就安全了吗?
不是。到期前的操作仍有风险,到期删除与集中重建也可能造成抖动;需要从数据建模和访问模式治理。
为什么集合扫描不能当精确分页?
SCAN 家族不提供稳定快照,变更期间可能出现重复或不确定结果。业务需要稳定页码和一致结果时,应采用有明确排序与边界的数据模型。