
# 发现和处理Redis大Key热Key
#### 大Key和热Key的定义
![](https://support.huaweicloud.com/bestpractice-dcs/public_sys-resources/note_3.0-zh-cn.png)
大Key和热Key场景较多，没有非常明确的边界，需要根据实际业务判断。
| 名词   | 定义                                                                                                                                                                                                                                                                                                                                                                          |
|:---|:---|
| 大Key | 大Key可以分为两种情况： - Key的Value占用存储空间较大。一般单个String类型的Key大小达到10KB，或者集合类型的Key总大小达到50MB，则被定义为大Key。  - Key的元素较多。一般集合类型的Key中元素超过5000个，则被定义为大Key。                                 |
| 热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的迁移，后续Key的数据会放到迁移机的内存Buffer中，如果阻塞时间太久，则会导致迁移失败。                                                                                                                                                                                                          |
| 大Key | **容易造成集群分片不均的情况。** - 各分片内存使用不均。例如某个分片占用内存较高甚至首先使用满，导致该分片Key被逐出，同时也会造成其他分片的资源浪费。  - 各分片的带宽使用不均。例如某个分片被频繁流控，其他分片则没有这种情况。   |
| 大Key | **客户端执行命令的时延变大。** 对大Key进行的慢操作会导致后续的命令被阻塞，从而导致一系列慢查询。                                                                                                                                                                                                                                                   |
| 大Key | **导致实例流控。** 对大Key高频率的读会使得实例出方向带宽被打满，导致流控，产生大量命令超时或者慢查询，业务受损。                                                                                                                                                                                                                                          |
| 大Key | **导致主备倒换。** 对大Key执行危险的DEL操作可能会导致主节点长时间阻塞，从而导致主备倒换。                                                                                                                                                                                                                                                    |
| 热Key | **容易造成集群分片不均的情况。** 造成热Key所在的分片有大量业务访问而同时其他的分片压力较低。这样不仅会容易产生单分片性能瓶颈，还会浪费其他分片的计算资源。                                                                                                                                                                                                                    |
| 热Key | **使得CPU冲高。** 对热Key的大量操作可能会使得CPU冲高，如果表现在集群单分片中就可以明显地看到热Key所在的分片CPU使用率较高。这样会导致其他请求受到影响，产生慢查询，同时影响整体性能。业务量突增场景下甚至会导致主备切换。                                                                                                                                                                                   |
| 热Key | **易造成缓存击穿。** 热Key的请求压力过大，超出Redis的承受能力易造成缓存击穿，即大量请求将被直接指向后端的数据库，导致数据库访问量激增甚至宕机，从而影响其他业务。                                                                                                                                                                                                                |
   
对于如何避免产生大Key和热Key，需要在业务设计阶段就考虑。参考[Redis使用规范](https://support.huaweicloud.com/bestpractice-dcs/dcs-bp-191113001.html)。
#### 如何发现大Key和热Key
| 方法                                       | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
|:---|:---|
| 使用DCS自带的大Key和热Key分析工具进行分析                | 请参考[分析Redis实例大Key和热Key](https://support.huaweicloud.com/usermanual-dcs/dcs-ug-190808001.html)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| 通过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命令查找大Key                          | 如果有已知的大Key模式，例如知道其前缀为cloud:msg:test，那么可以通过一个程序，SCAN符合该前缀的Key，然后通过查询成员数量和查询Key大小的相关命令，来判断具体的大Key。 - 查询成员数量的相关命令：LLEN，HLEN，XLEN，ZCARD，SCARD。  - 查询Key占用内存大小的命令：DEBUG OBJECT，MEMORY USAGE。   注意： 该方法会大量消耗计算资源，请知晓并评估其风险，不要在业务压力较大的实例使用该方法，否则可能会对正常业务造成影响。                                                                              |
| 通过redis-rdb-tools工具找出大Key                | [redis-rdb-tools](https://github.com/sripathikrishnan/redis-rdb-tools?spm=a2c4g.11186623.0.0.140745d6UhJnC6)是分析Redis RDB快照文件的开源工具。可以根据需求自定义分析Redis实例中所有Key的内存占用情况。 使用此方法需要在DCS实例备份与恢复页签中[导出实例的rdb文件](https://support.huaweicloud.com/usermanual-dcs/dcs-ug-0312034.html)。 注意： 该方法时效性相较于在线分析来说较差，优势在于完全不影响现有业务。                                                                                                                                                                |
   
#### 如何优化大Key和热Key
| 类别   | 方法                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
|:---|:---|
| 大Key | **进行大Key拆分。** 分为以下几种场景： - **该对象为String类型的大Key：**可以尝试将对象分拆成几个Key-Value， 使用MGET或者多个GET组成的pipeline获取值，分拆单次操作的压力。如果是集群实例，由于集群实例包含多个分片，拆分后的Key会自动平摊到集群实例的多个分片上，从而降低对单个分片的影响。  - **该对象为集合类型的大Key，并且需要整存整取：**在设计上严格禁止这种场景的出现，因为无法拆分。有效的方法是将该大Key从Redis去除，单独放到其余存储介质上。  - **该对象为集合类型的大Key，每次只需操作部分元素：**将集合类型中的元素分拆。以Hash类型为例，可以在客户端定义一个分拆Key的数量N，每次对HGET和HSET操作的field计算哈希值并取模N，确定该field落在哪个Key上，实现上类似于Redis Cluster的计算slot的算法。   |
| 大Key | **将大Key单独转移到其余存储介质。** 无法拆分的大Key建议使用此方法，将不适用Redis能力的数据存至其它存储介质，如[SFS](https://www.huaweicloud.com/product/sfs.html)或者其余NoSQL数据库，并在Redis中删除该大Key。 注意： 禁止使用DEL直接删除大Key，可能会造成Redis阻塞，甚至主备倒换。Redis 4.0及以上版本建议采用UNLINK命令删除大Key。                                                                                                                                                                                                                                                                                                                                                                                                              |
| 大Key | **合理设置过期时间并对过期数据定期清理。** 合理设置过期时间，避免历史数据在Redis中大量堆积。由于Redis的惰性删除策略，过期数据可能并不能及时清理，如果发现Redis过期Key清理较慢，建议配置[过期Key扫描](https://support.huaweicloud.com/usermanual-dcs/dcs-ug-210330002.html)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 热Key | **使用读写分离。** 如果热Key主要是读流量较大，则可以在客户端[配置读写分离](https://support.huaweicloud.com/dcs_faq/dcs-faq-0427027.html)，降低对主节点的影响。还可以增加多个副本以满足读需求，但是备机较多也有相应的影响，DCS主备节点之间使用的是星型复制，即所有的备节点都直接和主节点保持同步，这样能保证备节点之间相互独立，且复制延迟较小。缺点是在备节点数量较多的情况下，主节点的CPU和网络负载会较高。                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| 热Key | **使用客户端缓存/本地缓存。** 该方案需要提前了解业务的热点Key有哪些，设计客户端/本地和远端Redis的两级缓存架构，热点数据优先从本地缓存获取，写入时同时更新，这样能够分担热点数据的大部分读压力。缺点是需要修改客户端架构和代码，改造成本较高。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| 热Key | **设计熔断/降级机制。** 热Key极易造成缓存击穿，高峰期请求都直接透传到后端数据库上，从而导致业务雪崩。因此热Key的优化一定需要设计系统的熔断/降级机制，在发生击穿的场景下进行限流和服务降级，保护系统的可用性。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
   
