Redis内存占用过高,该如何解决?

一、需求背景

1.1背景

项目历史悠久,迭代多年,经过众多同事接手。对于缓存的使用存在许多不合理之处,导致了许多keys冗余:

  • 编码层面:序列化方式不统一、数据结构使用不合理造成存储空间冗余、用户数据膨胀导致数据堆积产生的大key、没有设置过期时间的key等等。

  • 业务层面:历史需求、运营活动等,存在一批已经停止使用但一直存储在实例中的key。

1.2优化的原因

1.2.1昂贵的费用

目前项目采用了128G的集群,八台实例,平均内存占用70-80G,大概2亿个key。Redis的费用非常昂贵,贴一张阿里云相近规格收费的图。

1.2.2大key存在的隐患

大key会带来的问题如下:

1、集群模式在slot分片均匀情况下,会出现数据和查询倾斜情况,部分有大key的Redis节点占用内存多,QPS高。

2、大key相关的删除或者自动过期时,会出现qps突降或者突升的情况,极端情况下,会造成主从复制异常,Redis服务阻塞无法响应请求。

基于以上原因,需要对项目的缓存进行优化。

二、优化思路

2.1分析key的使用情况

谈到缩容,最直接的方法肯定是分析出占用内存最大的key,对其进行优化。从此处开始,文章中提到的大key不单指单个大key,类似几百万数据的hash集合;也包含了一类key的占用了较大的空间,例如实例存在1000万个 user:info:{userid} 的string类型的key,我们也将它称为大key。

2.1.1key的采集与分析

列举分析常用的样本采集方案

方案 优缺点 是否选用
bigkeys命令 优点:使用简单 缺点:耗时较长,只能统计五种基础数据,无法对一类key名称进行匹配,只能找出单个大key
在单台实例执行bgSave,dump下来对应的RDB文件,使用对应的分析工具进行分析。我们使用的是rdb_bigkeys 优点:对业务不造成影响,本地数据,随时可以进行分析 缺点:时效性较弱
扫描脚本,使用scan命令配合扫描整台实例的keys 优点:支持任意数据类型,时效性高 缺点:虽然scan命令不阻塞主线程,但是大范围扫描keys还是会加重实例的IO,可以闲时再执行。

分析keys的使用,对于时效性要求肯定是不高的,所以选用了方案2,分析RDB文件,并定位key的影响范围。截取部分分析结果图:

2.1.2优化方案

分析出了大key后,就可以按keys的占用空间来排序,从前往后按优先级归纳需要优化的keys。项目中keys存在的问题在最开始已经总结过。

对于不合理的keys,我们分为两类:

  • 需要优化改进的keys
  • 可以直接删除的keys

一、需要优化改进的keys

这就需要针对业务场景做针对性处理了,只能给出一些典型例子的建议:

  • 选择合理的过期时间,结合业务能短尽量短。

  • 选择合适的数据结构:例如我们现在设计一个key用于存储一些信息。假定key和value的大小用了16个字节,但是由于RedisObject32b(元数据 8b+SDS指针8b+16b key value数据)、dictEntry 32b(三个指针24b,jellmoc分配出32b)。导致一个string的key需要存64b,冗余了很多数据。

    优化方式:将每个Key取hash code,然后按照业务对指定的业务分成n片,用hash code对n取模。此时我们使用hset info:{hash code%n} {key} {value}存储,通过修改hash-max-ziplist-entries(用压缩列表保存时哈希集合中的最大元素个数)和hash-max-ziplist-value(用压缩列表保存时哈希集合中单个元素的最大长度)来控制hash使用ziplist存储,节省空间。 这样可以节省dictEntry开销,剩下32b的空间。

    具体详情可以阅读 Redis核心技术实战 的第11章,讲得非常清晰。

  • 使用一定的序列化方式压缩存储空间,例如protobuf。

二、可以直接删除的keys

对于可以直接删除的keys,建议使用scan命令+unlink命令删除,避免主线程阻塞。我们采用的删除方式是:scan轮流扫描各个实例,匹配需要删除的Keys。

风险点:

大家都知道对于客户端命令的执行,Redis是单线程处理的,所以存在一些阻塞主线程的操作风险:

  • 对于一个占用内存非常大的key,不可直接使用del命令。

    解决方案:Redis4.0以上支持unlik命令异步删除。如果Redis版本小于4.0,建议对集合类采用hscan、zscan等命令分段删除。直接删除耗时可以参考:

  • Redis具有定时清理过期keys的策略,若有大批key在同一时间过期,会导致每次采样过期的keys都超过采样数量的25%,循环进行删除操作,影响主线程性能。可参考:定期删除策略

    解决方案:避免对大量key使用expiret加指定过期时间,需要将过期时间+随机数打散过期时机;由于我们的集群使用5.0版本,定位到定时清除过期Keys的代码serverCron()->databasesCron()->activeExprireCycle()→dbSyncDelete() ,内部删除方式采用unlink异步删除,不影响主线程。

  • 评估删除了keys对业务的影响

    解决方案:需要结合业务进行风险点评估;做好数据监控,例如异常告警、MySQL的QPS等。

三、优化了许多keys,内存占用还是很高,怎么回事?

Redis日常的使用是会存在内存碎片的,可在客户端执行info memory命令。如果mem_fragmentation_ratio值大于1.5,那么说明内存碎片超过50%,需要进行碎片整理了

解决方案

  • 重启Redis实例,暴力解决,不推荐

  • 使用 config set activedefrag yes 命令,调整以下参数进行自动清理

三、优化成果

删除掉一批弃用的keys后,Redis内存占用已经减少了10G。代码上的优化由于业务需求,有些key零散地设置了2-3个月的过期时间,两三个月过后刚好又迎来了淡季,无法准确预估优化了多少空间,但是总归还是有一定的成果。过程的思路和方案仅供参考。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容