1-Redis5 - 大key热key过期key删除策略

about

参考:

本篇我们主要探讨以下几个问题:

  • 过期key删除机制。
  • 大key/热key分析。
  • 如何揪出来那些大key和热key?
  • 内存策略。

过期key删除机制

来了解下redis关于过期key的删除机制。

  • 惰性删除:当我们使用惰性删除时,数据到期了也不会自动删除,那么他的删除方式是,在下一次在获取这个key值时,会做一个判断,判断这个key是否过期,如果过期了在执行删除。也就是说当再次执行get name时 会走一个函数expirelfNeeded() 这个函数就是判断此key是否过期的。过期的返回nil,然后从内存在进行删除。
  • 定期删除:由Redis的定时任务函数实现,该函数以一定的频率运行,每次运行时,都从键空间中取出一定数量的随机Key进行检查,并删除其中的过期键。注意:不是每次定时任务都会检查所有的Key,而是随机检查一定数量的Key,该机制旨在防止阻塞Redis主进程太久而造成业务阻塞,所以会造成已过期的Key释放内存速度较慢。定期删除的周期受hz参数限制,具体可以看本篇博客的后序章节。

redis定期任务与hz参数的关系

为了定期检测资源和服务状态并根据预定策略执行相应的操作,Redis调用一个内部函数来执行多种后台任务,例如:

  • 计算LRU信息并清除过期key。
  • 关闭超时的客户端连接。
  • 整理hash类型的数据。
  • 执行RDB或AOF持久化相关操作。
  • 更新统计信息。

这些定期任务是Redis服务正常运行的保障,它们的执行频率由hz参数的值指定,默认为10,即每秒执行10次。

redis-cli info Server
redis-cli config get hz

# 永久修改该参数的值,可以在其配置文件中指定如下参数:
hz n     # n表示的是一个1~100返回的数值

典型应用场景

Redis会通过执行定期任务来主动清除过期key,执行过程如下:

  1. 从设置了过期时间的key的集合中随机检查20个key。
  2. 删除检查中发现的所有过期key。
  3. 如果检查结果中25%以上的key已过期,则开始新一轮任务。

如果过期key数量很多或者增加速度很快,而Redis的主动清除频率较低,过期key将占用大量的内存空间,可能会影响Redis服务的性能。适当调整hz参数的值,提高清除频率,能够很好地解决这个问题。

取值范围及设置建议

hz的取值范围为1~500。增大hz参数的值会提升各项定期任务的执行频率,但也会提高Redis服务的CPU使用率。默认值10在一般情况下已经可以满足需求,如果业务场景对于某些定期任务的执行频率有很高的要求,您可以尝试在100以内调整参数值。将hz的值增加到100以上对CPU使用率有相对较大的影响,请谨慎操作。

大key热key

摘自华为云分布式缓存DCS:https://support.huaweicloud.com/intl/zh-cn/dcs_faq/dcs-faq-0805001.html

什么是大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能力的数据存至其它存储介质,如SFS或者其余NoSQL数据库,并在Redis中删除该大Key。

注意:禁止使用DEL直接删除大Key,可能会造成Redis阻塞,甚至主备倒换。

合理设置过期时间并对过期数据定期清理。

合理设置过期时间,避免历史数据在Redis中大量堆积。由于Redis的惰性删除策略,过期数据可能并不能及时清理,如果发现Redis过期Key清理较慢。

热key

使用读写分离。

如果热Key主要是读流量较大,则可以在客户端配置读写分离,降低对主节点的影响。还可以增加多个副本以满足读需求,但是备机较多也有相应的影响,DCS主备节点之间使用的是星型复制,即所有的备节点都直接和主节点保持同步,这样能保证备节点之间相互独立,且复制延迟较小。缺点是在备节点数量较多的情况下,主节点的CPU和网络负载会较高。

使用客户端缓存/本地缓存。

该方案需要提前了解业务的热点Key有哪些,设计客户端/本地和远端Redis的两级缓存架构,热点数据优先从本地缓存获取,写入时同时更新,这样能够分担热点数据的大部分读压力。缺点是需要修改客户端架构和代码,改造成本较高。

设计熔断/降级机制。

热Key极易造成缓存击穿,高峰期请求都直接透传到后端数据库上,从而导致业务雪崩。因此热Key的优化一定需要设计系统的熔断/降级机制,在发生击穿的场景下进行限流和服务降级,保护系统的可用性。

如何揪出来大key和热key

通过redis-cli来分析

从Redis4.0开始,我们可以通过redis-cli的bigkeys和hotkeys参数查找大Key和热Key。

相关命令:

redis-cli --bigkeys
redis-cli --memkeys
redis-cli --hotkeys

对于redis3.x来说。

通过redis-rdb-tools工具找出大Key

redis-rdb-tools是分析Redis RDB快照文件的开源工具。可以根据需求自定义分析Redis实例中所有Key的内存占用情况。

首先你要在你的centos服务器上安装Python3的解释器,保证有Python3的解释器和pip。安装参考:centos7编译安装python311

yum install python-pip gcc python-devel -y
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
pip3 install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install rdbtools python-lzf -i https://pypi.tuna.tsinghua.edu.cn/simple
python3 setup.py install

分析rdb文件,下面的命令可以在任意目录执行,都会在执行命令的目录生成csv分析文件,你可以将该csv文件导出到本地,通过Excel打开该csv文件,就可以看到这个分析结果了。。

rdb -c memory /data/redis6379/redis6379.rdb -f rdb.csv
awk -F"," '{print $4,$3}' rdb.csv |sort -r

内存策略

[root@cs ~]# redis-cli config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
策略 描述
noeviction 不淘汰键,当内存空间满后再进行写入会返回错误,不影响读操作。
allkeys-lru 最近最少使用方式,当内存空间满后,会淘汰内存中最近最少使用的键,即最长时间未被访问的键,如果没有可删除的key,则退回到noeviction策略。
volatile-lru 最近最少使用类似,不过是当内存空间满后,在设置了过期时间的键中淘汰最近最少使用的键.
allkeys-lfu 最近最不常用方式,当内存满后,会淘汰内存中被访问次数最少的键.
volatile-lru 和上面类似,当内存满后,在设置了过期时间的键中淘汰访问次数最少的键.
allkeys-random 当内存使用满后,随机淘汰内存中的键,它可以是任意的键,不管你是常使用的还是不常使用的.
volatile-random 类似,内存使用满后,在设置了过期时间的键中淘汰任意的键.
volatile-ttl 在设置了过期时间的键中,淘汰即将过期的键.

常见问题

Error: ERR An LFU maxmemory policy is not selected, access frequency not tracked. Please note that when switching between policies at runtime LRU and LFU data will take some time to adjust.

redis5.0.7 + centos7.9

当我执行下面命令时发现报错:

[root@cs ~]# redis-cli --hotkeys

# Scanning the entire keyspace to find hot keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).

Error: ERR An LFU maxmemory policy is not selected, access frequency not tracked. Please note that when switching between policies at runtime LRU and LFU data will take some time to adjust.

原因,此时Redis的内存策略是:

[root@cs ~]# redis-cli config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"

解决办法,将内存策略设置为allkeys-lfu或者volatile-lfu后再尝试执行:

redis-cli config set maxmemory-policy allkeys-lfu


redis-cli config set maxmemory-policy allkeys-lfu
redis-cli --hotkeys
posted @ 2023-08-19 22:45  听雨危楼  阅读(356)  评论(0编辑  收藏  举报