Redis 性能刺客,大key
在使用
Redis
的过程中,如果未能及时发现并处理Big keys
(下文称为“大Key
”),可能会导致服务性能下降、用户体验变差,甚至引发大面积故障。本文将介绍
大Key
产生的原因、其可能引发的问题及如何快速找出大Key
并将其优化的方案。
一、大Key的定义
在Redis
中,大Key
是指占用了较多内存空间的键值对。大Key
的定义实际是相对的,通常以Key的大小和Key中成员的数量来综合判定,例如:
graph LR
A(大Key)
B(Key本身的数据量过大)
C(Key中的成员数过多)
D(Key中成员的数据量过大)
E(一个String类型的Key 它的值为5MB)
F(一个ZSET类型的Key 它的成员数量为1W个)
G(一个Hash类型的Key 成员数量虽然只有1K个但这些成员的Value总大小为100MB)
A --> B --> E
A --> C --> F
A --> D --> G
style B fill:#FFC0CB,stroke:#FFC0CB,stroke-width:2px
style C fill:#FFA07A,stroke:#FFA07A,stroke-width:2px
style D fill:#FFFFE0,stroke:#FFFFE0,stroke-width:2px
style E fill:#98FB98,stroke:#98FB98,stroke-width:2px
style F fill:#B2FFFF,stroke:#B2FFFF,stroke-width:2px
style G fill:#E6E6FA,stroke:#E6E6FA,stroke-width:2px
注意:上述例子中的具体数值仅供参考,在实际业务中,您需要根据
Redis
的实际业务场景进行综合判断。
二、大Key引发的问题
当Redis中存在大量的大键时,可能会对性能和内存使用产生负面影响,影响内容包括
客户端执行命令的时长变慢。
Redis内存达到maxmemory参数定义的上限引发操作阻塞或重要的Key被逐出,甚至引发内存溢出(Out Of Memory)。
集群架构下,某个数据分片的内存使用率远超其他数据分片,无法使数据分片的内存资源达到均衡。
对大Key执行读请求,会使Redis实例的带宽使用率被占满,导致自身服务变慢,同时易波及相关的服务。
对大Key执行删除操作,易造成主库较长时间的阻塞,进而可能引发同步中断或主从切换。
上面的这些点总结起来可以分为三个方面:
graph LR
A(大Key引发的问题)
B(内存占用)
C(网络传输延迟)
D(持久化和复制延迟)
A ---> B
A ---> C
A ---> D
style B fill:#FFC0CB,stroke:#FFC0CB,stroke-width:2px
style C fill:#FFA07A,stroke:#FFA07A,stroke-width:2px
style D fill:#FFFFE0,stroke:#FFFFE0,stroke-width:2px
三、大Key产生的原因
未正确使用Redis
、业务规划不足、无效数据的堆积、访问量突增等都会产生大Key
,如:
在不适用的场景下使用
Redis
,易造成Key
的value
过大,如使用String
类型的Key
存放大体积二进制文件型数据;业务上线前规划设计不足,没有对
Key
中的成员进行合理的拆分,造成个别Key
中的成员数量过多;未定期清理无效数据,造成如
HASH
类型Key
中的成员持续不断地增加;使用
LIST
类型Key
的业务消费侧发生代码故障,造成对应Key
的成员只增不减。
上面的这些点总结起来可以分为五个方面:
graph LR
A(大Key产生的原因)
B(存储大量数据)
C(缓存过期策略错误)
D(冗余数据)
E(序列化格式选择不当)
F(数据结构选择不当)
A ---> B
A ---> C
A ---> D
A ---> E
A ---> F
style B fill:#FFC0CB,stroke:#FFC0CB,stroke-width:2px
style C fill:#FFA07A,stroke:#FFA07A,stroke-width:2px
style D fill:#FFFFE0,stroke:#FFFFE0,stroke-width:2px
style E fill:#98FB98,stroke:#98FB98,stroke-width:2px
style F fill:#B2FFFF,stroke:#B2FFFF,stroke-width:2px
四、如何快速找出大Key
要快速找出Redis
中的大键,可以使用Redis
的命令和工具进行扫描和分析。以下是一些方法:
使用Redis命令扫描键:
Redis
提供了SCAN
命令,可以用于迭代遍历所有键。您可以使用该命令结合适当的模式匹配来扫描键,并在扫描过程中获取键的大小(使用MEMORY USAGE
命令)。通过比较键的大小,您可以找出占用较多内存的大键。使用Redis内存分析工具:有一些第三方工具可以帮助您分析
Redis
实例中的内存使用情况,并找出大键。其中一种常用的工具是Redis
的官方工具Redis Memory Analyzer (RMA)
。您可以使用该工具生成Redis
实例的内存快照,然后分析快照中的键和它们的大小,以找出大键。使用Redis命令和Lua脚本组合:您可以编写Lua脚本,结合
Redis
的命令和Lua
的逻辑来扫描和分析键。通过编写适当的脚本,您可以扫描键并获取它们的大小,然后筛选出大键。
现在大部分都是使用的
云Redis
,其本身一般也提供了多种方案帮助我们轻松找出大Key
,具体可以参考一下响应云Redis
的官网使用文档。
五、大Key的优化方案
大Key
会给我们的系统带来性能瓶颈,所以肯定是要进行优化的,那么下面来介绍一下大Key
都可以怎么优化。
5.1 对大Key进行拆分
例如将含有数万成员的一个HASH Key
拆分为多个HASH Key
,并确保每个Key
的成员数量在合理范围。在Redis
集群架构中,拆分大Key
能对数据分片间的内存平衡起到显著作用。
5.2 对大Key进行清理
将不适用Redis能力的数据存至其它存储,并在Redis中删除此类数据。
注意
Redis 4.0及之后版本:可以通过UNLINK命令安全地删除大Key甚至特大Key,该命令能够以非阻塞的方式,逐步地清理传入的Key。
Redis 4.0之前的版本:建议先通过SCAN命令读取部分数据,然后进行删除,避免一次性删除大量key导致Redis阻塞。
5.3 对过期数据进行定期清理
堆积大量过期数据会造成大Key
的产生,例如在HASH
数据类型中以增量的形式不断写入大量数据而忽略了数据的时效性。可以通过定时任务的方式对失效数据进行清理。
注意:在清理HASH数据时,建议通过
HSCAN
命令配合HDEL
命令对失效数据进行清理,避免清理大量数据造成Redis
阻塞。
5.4 特别说明
如果你用的是云
Redis
服务,要注意云Redis
本身带有的大key
的优化方案
六、总结
本文介绍了大Key
在Redis
中的定义以及可能引发的问题。介绍了快速找出大Key
的方法以及对于大Key
的优化方案。通过合理的优化方案,可以提升Redis
的性能和用户体验。
希望本文对您有所帮助。如果有任何错误或建议,请随时指正和提出。
同时,如果您觉得这篇文章有价值,请考虑点赞和收藏。这将激励我进一步改进和创作更多有用的内容。
感谢您的支持和理解!
来源:juejin.cn/post/7298989375370166298