本文详细讲解了Rediskey中BigKey和HotKey的发现和处理”)。如果不及时检测和处理大key和hotkey,很可能会降低服务性能,恶化用户体验,甚至造成大-scalefailures.两个bigkey和hotkey的定义我们经常可以在公司内部的Redis开发使用规范手册,或者网上大量的Redis最佳实践文章中看到bigkey和hotkey的定义,这些资料中的bigkeys判断热键的标准不同,但很明显它们的判断维度是一样的:大键通常是根据数据大小和成员数来判断,而热键是根据频率来判断以及他们收到的请求数量。确定。1什么是大密钥?通常我们称包含大量数据或大量成员的密钥或列出大密钥。下面我们将使用几个实际示例描述一个大key的特点:一个STRING类型的key,它的值为5MB(数据太大),一个LIST类型的Key,它的列表个数是20000(列表个数太大),一个ZSETtypeKey,其成员数为10000(成员数太大)aHASH格式的key只有1000个成员,但这些成员的总值为100MB(成员数太大)。需要注意的是,在上面的例子中,为了便于理解,我们使用大key、Members、listcounts的数据给出了具体的数字。为了避免误导,在实际业务中,大key的判断还是需要根据Redis的实际使用场景和业务场景综合判断。2什么是热键当某个键的访问量明显高于其他键时,我们可以称它为热键。常见的热键如:Redis实例每秒总访问次数为10000次,其中一个Key每秒访问次数为7000次(访问次数明显高于其他Key)。每秒发送大量的HGETALLs到一个拥有几千个成员且总大小为1MB的HASHKey(带宽占用明显高于其他Key))每秒发送大量的ZRANGE到一个数万个的ZSETKey成员(CPU时间明显高于其他Key)。Redis带来了各种各样的问题,最常见的问题是性能下降、访问超时、数据不平衡等。1大key引起的常见问题客户端发现Redis变慢;Redis内存持续增长导致OOM,或者达到maxmemory设置值导致写阻塞或者重要key被驱逐;RedisCluster中某个节点的内存远远多于其他节点,但是由于RedisCluster数据迁移的最小粒度是Key,节点上的内存无法均衡;对大Keys的读取请求导致Redis占用服务器的全部带宽,降低自身速度并影响服务器上的其他服务;删除一个大key导致主库长时间阻塞导致同步中断或主从切换;2热键引起的常见问题热键占用大量RedisCPU时间,使其性能变差,影响其他请求;RedisCluster中的各个节点由于流量不均衡,导致RedisCluster的分布式优势无法被Client发挥出来。一个分片负载高,而其他分片非常空闲,导致读写热点;过大,超过Redis的处理能力,导致超卖;热键的请求压力超过Redis的容量,导致缓存崩溃。热键常见原因业务规划不充分、Redis使用不当、无效数据堆积、访问量突然增加等都会产生大键和热键,例如:在不适合其能力的场景中使用Redis,导致keyfailure值太大,比如使用String类型的Key存储大容量二进制文件类型数据(largeKey);业务上线前规划设计考虑不充分,没有合理拆分Key中的成员,导致单个Key(LargeKey)成员过多;未能定期清理无效数据,导致HASH类型Key(LargeKey)成员数不断增加;不期而至的访问量骤增,如突然爆炸,访问量暴涨热点新闻,主播在直播间带来的刷屏大量点赞,某区多个工会的大战涉及大量玩家的游戏等(热键);业务消费端使用LIST类型Key的代码失效,Key对应的成员只增不减(bigKey);5、在Redis中找出bigKey和hotKey并不难。bigKey和hotKey的分析并不难。分析找到“问题”键,比如Redis的内置函数、开源工具、阿里云Redis控制台的键值分析功能。1使用Redis自带的查找大键和热键的功能。Redis内置的一些命令和工具可以帮助我们找到这些问题键。当你对Redis的bigkey和hotkey有了明确的分析目标后,可以使用如下命令来分析对应的key。通过Redis内置命令解析目标Key。您可以选择使用debugobject命令来分析Key。该命令可以根据传入的对象(Key的名称)来解析Key并返回大量数据,其中serializedlength的值为Key的序列化长度,您可以选择使用该数据来判断是否对应的Key符合你BigKey的判断标准。需要注意的是,Key序列化后的长度并不等于它在内存空间中的真实长度。另外,debug对象是一个调试命令,运行起来开销很大,而且在运行时,其余进入Redis的请求都会被阻塞。阻塞直到它的执行完成。该命令的运行时间取决于传入对象(键名)的序列化长度。所以线上环境下不建议使用该命令分析大key,容易导致失败。从Redis4.0开始,提供了MEMORYUSAGE命令来帮助分析Key的内存使用情况。与debug对象相比,其执行成本较低,但由于其时间复杂度为O(N),在分析大Key时仍存在阻塞风险。我们建议以风险较小的方式分析密钥。Redis针对不同的数据结构提供了不同的命令来返回其长度或者成员个数,如下表所示:通过以上Redis内置的命令,我们可以方便安全的分析Key不会影响在线服务,但是因为它们返回的结果并不是Key真正的内存使用数据,不够准确,只能作为参考。通过Redis官方客户端redis-cli的bigkeys参数查找bigkey如果你没有明确的目标key进行分析,又想借助工具找出整个Redis实例中的bigkey,那么bigkeys参数redis-cli可以方便的帮你实现这个目标。Redis提供了bigkeys参数,可以让redis-cli以遍历的方式分析整个Redis实例中的所有Key,并将结果汇??总成一个报告。这种方案的优点是方便和安全,但缺点也很明显:无法自定义分析结果。bigkeys只能输出六个Redis数据结构中最大的Key。如果只想分析STRING类型或者找出10个以上成员的HASHKey,那么bigkeys在这种需求场景下就力不从心了。GitHub上有大量的开源项目可以实现bigkeys的增强版,从而可以根据配置定制结果。另外,你也可以使用SCAN+TYPE,配合上表中的命令,自己实现一个Redis实例级的大键解析。工具。同样,该解决方案的实现方式和返回的结果使其不精确和实时,建议仅作为参考。通过Redis官方客户端redis-cli的hotkeys参数发现hotkeysRedis从4.0开始就提供了hotkeys参数,方便在实例级别进行用户级的热键分析。这个参数可以返回所有key的访问次数,它的缺点也是不可能的。自定义输出报告,大量的信息会让你的分析结果更加复杂。另外,使用该方案的前提是将redis-server的maxmemory-policy参数设置为LFU。通过业务层定位热键每一次对Redis的访问都来自于业务层,所以我们可以通过在业务层添加相应的代码来记录和异步汇总分析对Redis的访问。该方案的优点是可以准确及时地分析热键的存在。缺点是增加了业务代码的复杂度,可能会降低一些性能。在紧急情况下使用monitor命令查找热键。Redis的monitor命令可以忠实打印Redis中的所有请求,包括时间信息、Client信息、命令、Key信息。在紧急情况下,我们可以简单地执行monitor命令并将输出重定向到一个文件。关闭监控命令后,我们可以通过对文件中的请求进行分类分析,找出这段时间的热键。因为monitor命令占用了Redis一定的CPU、内存、网络资源。所以,对于一个已经处于高压状态的Redis来说,monitor可能起到了更差的作用。同时,这种异步采集分析方案的时效性较差,而且由于分析的准确性依赖于monitor的执行时间,所以在线上大部分无法下达命令的场景下,这种方案的准确性不够执行了好久。2使用开源工具发现KeyRedis的高人气使得我们可以很容易地找到大量的开源解决方案来解决我们目前的问题:在不影响在线服务的情况下得到准确的分析报告。使用redis-rdb-tools工具以自定义方式查找大键。如果你想按照自己的标准准确分析Redis实例中所有key的真实内存使用情况,避免影响在线服务,可以在分析后得到一份简明的副本。对于易于理解的报告,redis-rdb-tools是一个非常好的选择。本工具可以对RedisRDB文件进行自定义分析,但由于RDB文件的分析是离线进行的,不会对线上业务造成任何影响。这是它最大的优势,也是它最大的劣势:离线分析代表分析结果的时效性差。对于一个大的RDB文件,它的分析可能会持续很长时间。3依托公有云的Redis分析服务发现bigkey和hotkey如果你期望能够实时分析Redis实例中的所有key,发现当前的bigkey和hotkey,知道Redis有在运行时间线上出现了哪些大键和热键,这样可以对整个Redis实例的运行状态有一个全面准确的判断,而公有云的Redis控制台会满足这个需求。阿里云Redis控制台CloudDBACloudDBA是阿里云的智能数据库服务系统,支持Redislargekey和hotkey的实时分析和发现。bigkey和hotkey解析底层是阿里云Redis内核的key解析功能。该函数通过Redis内核直接发现并输出bigkey和hotkey的信息。因此,该函数的分析结果准确高效,对性能几乎没有影响。影响,可以在CloudDBA中点击“KeyAnalysis”进入该功能,如下图1-1所示:图1-1:阿里云Redis控制台CloudDBAKey分析功能有两个页面,可以对不同时间维度的数据进行分析Redis实例中的Keys:实时:立即开始分析当前实例,并显示当前存在的所有大键和热键。历史记录:显示最近在本实例中出现过的大键和热键。在历史页面上,所有出现过的大键和热键都会被记录下来,即使这些键已经不存在了。该功能可以很好的反映出Redis的历史关键状态,有助于追溯过去或者站点被破坏的问题。六大键和热键的处理现在,我们已经通过各种方式发现了Redis中的问题键,所以我们应该马上着手处理,以免以后造成问题。1大键的常用处理方法拆分大键,如将一个拥有几万个成员的HASH键拆分成多个HASH键,并保证每个键的成员数在合理范围内。在RedisCluster结构中,大的Key分裂可以对节点间的内存平衡起到很大的作用。清理大键,将不适合Redis能力的数据存储到其他存储,删除Redis中的此类数据。需要注意的是,我们上面已经提到过,Key过大可能会导致Redis集群同步中断。Redis从4.0开始提供了UNLINK命令,可以以非阻塞的方式慢慢地逐步清理传入的Key,通过UNLINK,你可以安全的删除一个大的key,甚至是非常大的key。时刻监控Redis的内存水平,突然出现大key问题会让我们措手不及。因此,发现并处理大的关键问题,是维护服务稳定的重要手段。我们可以对系统进行监控,设置合理的Redis内存告警阈值,提醒我们此时可能有较大的key正在生成,比如:Redis内存使用率超过70%,1小时内Redis内存增长率超过20%,等等,通过这样的监控手段,可以防患于未然。比如LIST的消费者程序失败导致Key对应的列表数量不断增加,将告警转为预警,避免失败的发生。定期清理无效数据。比如我们会在HASH结构中以增量的形式不断写入大量的数据,而忽略了这些数据的时效性。这些大量积累的无效数据会导致大key的产生,可以通过定时任务来实现。清除无效数据的方法。此类场景建议使用HSCAN,配合HDEL清理无效数据。该方法可以在不阻塞的情况下清理无效数据。使用阿里云的Tair(Redis企业版)服务,避免无效数据的清洗。如果你的HASH键太多,就会有大量的无效成员需要清理。由于大量key和大量无效数据的叠加,这种场景下定时任务是不可能清理无效数据的。阿里云的Tair服务可以很好的解决这个问题。Tair是阿里云的Redis企业版。它具有Redis的所有特性(包括Redis的高性能特性),并提供了大量额外的高级功能。TairHash是一个哈希类型的数据结构,可以设置字段的过期时间和版本。它不仅像RedisHash一样支持丰富的数据接口和高处理性能,而且改变了hash只能为key设置过期时间的限制:TairHash允许为field设置过期时间和版本。这大大提高了哈希数据结构的灵活性,简化了很多场景下的业务开发。TairHash使用高效的ActiveExpire算法,高效完成判断和删除字段过期的功能,对响应时间的影响很小。合理使用这些高级功能,可以解放大量的Redis运维和故障处理工作,降低业务代码的复杂度,让运维可以把精力投入到其他更有价值的工作上,让研发有更多的时间写更多的东西有价值的代码。2常用的热键处理方法。在RedisCluster结构中复制热键。在RedisCluster中,由于迁移粒度的原因,热键无法分散,无法降低单节点的压力。此时,可以复制对应的热键,迁移到其他节点。例如,为热键foo复制三个内容完全相同的键,分别命名为foo2、foo3、foo4,然后将这三个键迁移到其他节点即可解决问题。单节点热键压力。这种方案的缺点是需要结合修改代码。同时Keys的变化带来了数据一致性的挑战:从更新一个Key到同时更新多个Key。在很多情况下,这个方案只是被推荐用来暂时解决当前棘手的问题。使用读写分离架构如果热键的产生来自读请求,那么读写分离是一个很好的解决方案。在使用读写分离架构时,可以通过不断增加从节点的数量来降低各个Redis实例中的读请求压力。但是读写分离架构在增加业务代码复杂度的同时也增加了Redis集群架构的复杂度:我们不仅需要为多个从节点提供转发层(如Proxy、LVS等)来实现负载均衡,还需要考虑从节点数量大幅增加导致的故障率增加的问题。Redis集群架构的变化也给监控、运维、故障处理带来了更大的挑战。然而,这一切在阿里云Redis服务中都变得异常简单,开箱即用。同时,当业务发展发生变化时,阿里云的Redis服务可以让用户通过配置变更调整集群架构,轻松应对,例如:主从改造为读写分离、读写分离成集群、主-slave改造为了支持读写分离的集群,直接从社区版改造为支持大量高级特性的企业版Redis(Tair)。读写分离架构也有缺点。在请求量巨大的场景下,读写分离架构会产生不可避免的延迟。这时候就会出现读取脏数据的问题。因此,当读写压力大、数据一致性要求高的场景下,读写分离架构就不适用了。使用阿里云Tair的QueryCache特性QueryCache是??阿里云Tair(Redis企业版)服务的企业级特性之一。其原理如图2-1所示:图2-1:TairQueryCache原理排序统计算法识别实例中的热点key。开启该功能后,Proxy节点会按照设定的规则缓存热点key的请求和查询结果(只缓存热点key的查询结果,不需要缓存整个key)。当在缓存有效期内收到相同的请求时,Proxy会直接将结果返回给客户端,而无需与后端Redis分片进行交互。在提高读取速度的同时,降低热点key对数据分片的性能影响,避免请求倾斜。至此,客户端的同一个请求不需要在Proxy后端与Redis进行交互,Proxy直接返回数据。指向热key的请求由一个Redis节点承担,中转给多个Proxies,可以大大降低Redis节点的热度。同时Tair的QueryCache功能也提供了大量的命令方便用户查看和管理,比如通过querycachekeys命令查看所有缓存的热键,通过querycachelistall获取所有缓存的命令。TairQueryCache的智能热键判断和缓存联动功能也可以减少运维和研发的工作量。与传统的Redis同步中间件相比,阿里云的Redis全局分布式缓存具有高可靠、高吞吐、低延迟、高同步精度等特点。
