【后端面试题】【中间件】【缓存】Redis的大Key问题

大key的标准

一般的业务场景下,对并发和容量要求都不大:

  • 单个string的value超过1MB

  • 容器数据结构元素数量超过10000

在高并发且低延迟的场景里:

  • 单个string的value超过10KB

  • 容器数据结构元素数量超过5k或是整体value超过10MB

阿里云的云Redis:

  • Key本身的数据量过大:一个String类型的Key,它的值为5 MB。

  • Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10,000个。

  • Key中成员的数据量过大:一个Hash类型的Key,它的成员数量虽然只有2,000个但这些成员的Value(值)总大小为100 MB。

大Key的影响

  1. 读取成本高
  • 时延高,因为执行命令时间更长

  • 消耗更多的带宽,导致自身服务变慢,从而影响相关服务

  1. 大Key相关操作容易阻塞,从而导致无法正常响应
  • 慢查询变多

  • 删除的时候容易导致主库长时间的阻塞,进而可能引发同步中断或主从切换

  1. 占用更多的存储空间,内存达到maxmemory参数定义的上限引发操作阻塞或重要的key被逐出,甚至是OOM

  2. 集群架构下,某个数据分片的内存使用率远超其他数据分片,导致数据分片的内存资源分配不均衡

大key产生的原因

  1. 业务设计不合理:最常见的原因,不经过合理的拆分,就把大json塞在一个key里,甚至塞二进制文件数据。没有对key中的成员进行合理的拆分,造成个别key中的成员数量过多。

  2. 没有处理好value的动态增长问题。如果一直添加value数据的话,没有定期的删除机制、合理的过期机制,或是没有设定合适的阈值,早晚会变成大key。例如:微博明星的粉丝列表、热门评论、直播弹幕

  3. 程序bug:某些异常情况导致某些key的生命周期超出预期,或是value数量异常增长。使用LIST类型key的业务消费侧发生代码故障,造成对应的key的成员只增不减。

如何找到大key

云Redis提供的服务

云服务提供的实时Top Key统计服务或是离线全量Key分析服务

通过redis-cli的bigkeys命令

Redis提供了bigkeys参数能够使redis-cli以遍历的方式分析Redis实例中的所有key,并返回key的整体统计信息与每个数据类型中Top1的大key,bigkeys只能分析并输入六种数据类型(STRING,LIST,HASH,SET,ZSET,STREAM),命令示例

redis-cli -h r-***************.redis.rds.aliyuncs.com -a <password> --bigkeys

注意:若只需要分析STRING类型的大key或是找出成员数量超过10个的HASH Key,则bigkeys参数无法直接实现该类需求。

Redis RDB Tools工具

支持定制化分析的开源工具 GitHub - sripathikrishnan/redis-rdb-tools: Parse Redis dump.rdb files, Analyze Memory, and Export Data to JSON 通过分析RDB文件,扫描出Redis的大key

可以根据自己的精细化需求,全面地分析所有Key的内存占用情况,而且对线上服务无影响。但是因为RDB文件较大时耗时较长。

Redis内置命令

通过Redis内置命令对目标Key进行分析,可以使用风险较低的命令来查询目前Key的字节数、列表长度或成员数量

  • STRING类型:执行STRLEN命令,返回对应Key的value的字节数。

  • LIST类型:执行LLEN命令,返回对应Key的列表长度。

  • HASH类型:执行HLEN命令,返回对应Key的成员数量。

  • SET类型:执行SCARD命令,返回对应Key的成员数量。

  • ZSET类型:执行ZCARD命令,返回对应Key的成员数量。

  • STREAM类型:执行XLEN命令,返回对应Key的成员数量。

注意!!!

DEBUG OBJECTMEMORY USAGE命令在执行时需占用较多资源,且时间复杂度为O(N),有阻塞Redis实例的风险,不建议使用。

大Key优化

业务侧 – 根本

业务侧优先考虑避免大key设计,不要什么都往里放,仅仅缓存必要的数据字段

拆分 分片

例如将含有数万成员的一个HASH Key拆分为多个HASH Key,并保证每个Key的成员数量在合理范围。在Redis集群架构中,拆分大Key能对数据分片间的内存平衡起到显著作用

需要考虑下面几个问题:

  1. 定量拆分还是动态拆分?定量拆分需要考虑value增长的问题;动态分片就是先按原key读第一个分片,第一个分片的value记录分片的总数,然后再按照shard_num取。

  2. 存在部分写问题,比如写入10个分片的数据,只有5个分片写入成功,就会造成数据不一致问题。解决方案有下面几个

  • 引入版本机制

  • value最前面带上版本号

  • 一个分片不对就算错误,重新加载,容易陷入死循环

  1. 开发、维护、组装的成本

更换存储方案

换别的没有大key问题的存储

  1. 持久型kv存储
  • 软件:LSM-Tree

  • 硬件:固态存储

  1. 本地缓存,和redis结合实现多级缓存

  2. CDN

数据压缩

golang自带的zip和unzip可以对string类型的数据进行压缩

string类型

考虑使用容器型数据结构替换 string,提高内存利用效率,也能一定程度节省键名空间

合理的清理机制

对过期数据进行定期清理

堆积大量过期数据会造成大Key的产生,例如在HASH数据类型中以增量的形式不断写入大量数据而忽略了数据的时效性。可以通过定时任务的方式对失效数据进行清理。

在清理HASH数据时,建议通过HSCAN命令配合HDEL命令对失效数据进行清理,避免清理大量数据造成Redis阻塞。

对大Key进行清理

直接删除的话容易阻塞,因为Redis是单线程,从而影响到其他线上请求,超时增加的话会导致Redis连接打满,从而引发各种异常问题

解决方案:

  1. 选择业务流量低峰期的时候删除

  2. 分批定时定量删除:一次删除一部分,防止一次性删除大量数据导致阻塞

  • hash:hsacn扫描

  • set:srandmember 随机取数删除

  • zset:zremrangebyrank 移除指定排名(rank)区间内的所有元素

  • list:直接 pop 删

  1. 异步删除:用unlink代码del删除,只是将键与键空间断开连接,实际的删除异步进行,非阻塞,逐步清理

如何找出优化大Key与热Key,产生的原因和问题_云数据库 Redis 版(Redis)-阿里云帮助中心

redis 大key

  • 38
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值