什么是大Key/热Key?
名词 | 定义 |
---|---|
大Key | 大Key可以分为两种情况: Key的Value较大,例如一个String类型的Key大小达到10MB,或者一个集合类型(Hash,List,Set等)的元素总大小达到了100MB。一般单个String类型的Key大小达到10KB,或者集合类型的Key总大小达到50MB,则定义其为大Key。 Key的元素较多,例如一个Hash类型的Key,其元素数量达到了10000。一般定义集合类型的Key中元素超过5000个,则认为其为大Key。 |
热Key | 通常以一个Key被操作的频率和占用的资源来判定其是否为热Key,例如: 某个集群实例一个分片每秒处理10000次请求,其中有3000次都是操作同一个Key。 某个集群实例一个分片的总带宽使用(入带宽+出带宽)为100Mbits/s,其中80Mbits是由于对某个Hash类型的Key执行HGETALL所占用。 |
存在大Key/热Key,有什么影响?
类别 影响 大Key 造成规格变更失败。
Redis集群变更规格过程中会进行数据rebalance(节点间迁移数据),单个Key过大的时候会触发Redis内核对于单Key的迁移限制,造成数据迁移超时失败,Key越大失败的概率越高,大于512MB的Key可能会触发该问题。造成数据迁移失败。
数据迁移过程中,如果一个大Key的元素过多,则会阻塞后续Key的迁移,后续Key的数据会放到迁移机的内存Buffer中,如果阻塞时间太久,则会导致迁移失败。容易造成集群分片不均的情况。
各分片内存使用不均。例如某个分片占用内存较高甚至首先使用满,导致该分片Key被逐出,同时也会造成其他分片的资源浪费。
各分片的带宽使用不均。例如某个分片被频繁流控,其他分片则没有这种情况。客户端执行命令的时延变大。
对大Key进行的慢操作会导致后续的命令被阻塞,从而导致一系列慢查询。导致实例流控。
对大Key高频率的读会使得实例出方向带宽被打满,导致流控,产生大量命令超时或者慢查询,业务受损。导致主备倒换。
对大Key执行危险的DEL操作可能会导致主节点长时间阻塞,从而导致主备倒换。热Key 容易造成集群分片不均的情况。
造成热Key所在的分片有大量业务访问而同时其他的分片压力较低。这样不仅会容易产生单分片性能瓶颈,还会浪费其他分片的计算资源。使得CPU冲高。
对热Key的大量操作可能会使得CPU冲高,如果表现在集群单分片中就可以明显地看到热Key所在的分片CPU使用率较高。这样会导致其他请求受到影响,产生慢查询,同时影响整体性能。业务量突增场景下甚至会导致主备切换。易造成缓存击穿。
热Key的请求压力过大,超出Redis的承受能力易造成缓存击穿,即大量请求将被直接指向后端的数据库,导致数据库访问量激增甚至宕机,从而影响其他业务。
为了减少大Key和热Key过大,有什么使用建议?
- string类型控制在10KB以内 ,hash、list、set、zset 元素尽量不超过5000 。
- Key的命名前缀为业务缩写,禁止包含特殊字符(比如空格、换行、单双引号以及其他转义字符)。
- Redis事务功能较弱,不建议过多使用。
- 短连接性能差,推荐使用带有连接池的客户端。
- 如果只是用于数据缓存,容忍数据丢失,建议关闭持久化。
- 大Key/热Key的优化方法,请参考下表。
类别 方法 大Key 进行大Key拆分。
分为以下几种场景
该对象为String类型的大Key:可以尝试将对象分拆成几个Key-Value, 使用MGET或者多个GET组成的pipeline获取值,分拆单次操作的压力,对于集群来说可以将操作压力平摊到多个分片上,降低对单个分片的影响。
该对象为集合类型的大Key,并且需要整存整取:**在设计上严格禁止这种场景的出现,因为无法拆分。有效的方法是将该大Key从Redis去除,单独放到其余存储介质上。
该对象为集合类型的大Key,每次只需操作部分元素:**将集合类型中的元素分拆。以Hash类型为例,可以在客户端定义一个分拆Key的数量N,每次对HGET和HSET操作的field计算哈希值并取模N,确定该field落在哪个Key上,实现上类似于Redis Cluster的计算slot的算法。将大Key单独转移到其余存储介质。
无法拆分的大Key建议使用此方法,将不适用Redis能力的数据存至其它存储介质,并在Redis中删除该大Key。
注意
禁止使用DEL直接删除大Key,可能会造成Redis阻塞,甚至主备倒换。热Key 使用客户端缓存/本地缓存。
该方案需要提前了解业务的热点Key有哪些,设计客户端/本地和远端Redis的两级缓存架构,热点数据优先从本地缓存获取,写入时同时更新,这样能够分担热点数据的大部分读压力。缺点是需要修改客户端架构和代码,改造成本较高。设计熔断/降级机制。
热Key极易造成缓存击穿,高峰期请求都直接透传到后端数据库上,从而导致业务雪崩。因此热Key的优化一定需要设计系统的熔断/降级机制,在发生击穿的场景下进行限流和服务降级,保护系统的可用性。
如何分析Redis 3.0实例的热Key?
由于Redis 3.0本身不提供热Key能力,您可以参考以下方法进行分析。
- 方法1:进行业务结构和业务实现分析,找到可能的热Key。
例如,某商品在秒杀,或者用户登录,对业务代码分析,很容易找到热Key。
优点:简单易行。
缺点:需要对业务代码比较了解,另外对于一些复杂的业务场景,不太容易分析。
- 方法2:在客户端代码中,调用Redis的函数中,进行访问Key的记录,进而统计出热Key。
缺点:需要代码进行侵入式修改。
- 方法3:抓包分析
优点:简单易行
如何提前发现大Key和热Key?
方法 | 说明 |
---|---|
使用DCS自带的大Key和热Key分析工具进行分析 | 请参考缓存分析。 |
通过redis-cli的bigkeys和hotkeys参数查找大Key和热Key | Redis-cli提供了bigkeys参数,能够使redis-cli以遍历的方式分析Redis实例中的所有Key,并返回Key的整体统计信息与每个数据类型中Top1的大Key,bigkeys仅能分析并输入六种数据类型(STRING、LIST、HASH、SET、ZSET、STREAM),命令示例为:redis-cli -h <实例的连接地址> -p <端口> -a <密码> --bigkeys。 自Redis 4.0版本起,redis-cli提供了hotkeys参数,可以快速帮您找出业务中的热Key,该命令需要在业务实际运行期间执行,以统计运行期间的热Key。命令示例为:redis-cli -h <实例的连接地址> -p <端口> -a <密码> --hotkeys。热Key的详情可以在结果中的summary部分获取到。 |
对于Redis 3.0实例,由于Redis 3.0本身不支持热Key分析,推荐可以使用配置告警的方法,帮助您发现热Key。
- 配置节点级别的内存利用率监控指标的告警
如果某个节点存在大key,这个节点比其他节点内存使用率高很多,会触发告警,便于用户发现潜在的大key。
- 配置节点级别的 入网最大带宽、出网最大带宽 、CPU利用率监控指标的告警
如果某个节点存在热key,这个节点的带宽占用、CPU利用率都比其他节点高,该节点会容易触发告警,便于用户发现潜在热key。