为什么Redis内存不宜过大

这几年的线上业务表明,redis这个内存数据库,它的高性能、稳定性都是不用怀疑的,但我们塞进redis的数据过多,内存过大,那如果出问题,那它可能会带给我们的就是灾难性(我想很多公司都遇到过) 这里列举一下,我们遇到的一些问题:

1 主库宕机

先来看一下主库宕机容灾过程:如下图

在主库宕机的时候,我们最常见的容灾策略为“切主”。具体为从该集群剩余从库中选出一个从库并将其升级为主库,该从库升级为主库后再将剩余从库挂载至其下成为其从库,最终恢复整个主从集群结构。

以上是一个完整的容灾过程,而代价最大的过程为从库的重新挂载,而非主库的切换。

这是因为redis无法像mysql、mongodb那样基于同步的点位在主库发生变化后从新的主库继续同步数据。 在redis集群中一旦从库换主,redis的做法是将更换主库的从库清空然后从新主库完整同步一份数据再进行续传。

整个从库重做流程是这样的:

  1. 主库bgsave自身数据到磁盘
  2. 主库发送rdb文件到从库
  3. 从库开始加载
  4. 加载完毕开始续传,同时开始提供服务

很明显,在这个过程中redis的内存体积越大以上每一个步骤的时间都会被拉长,实际测试的数据如下(我们自认我们的机器性能比较好):

可以看到,当数据达到20G的时候,一个从库的恢复时间已经被拉长到了将近20分钟,如果有10个从库那么如果依次恢复则共需200分钟,而如果此时该从库承担着大量的读取请求你能够忍受这么长的恢复时间吗?

看到这里你肯定会问:为什么不能同时重做所有从库?这是因为所有从库如果同时向主库请求rdb文件那么主库的网卡则立即跑满从而进入一个无法正常提供服务的状态,此时主库又死了,简直是雪上加霜。

当然,我们可以批量恢复从库,例如两两一组,那么全部从库的恢复时间也仅仅从200分钟降低到了100分钟,这不是五十步笑百步吗?

另一个重要问题在于第四点中的标红位置,续传可以理解为一个简化的mongodb的oplog,它是一个体积固定的内存空间,我们称之为“同步缓冲区”。

redis主库的写入操作都会在该区域存放一份然后发送给从库,而如果在上文中1,2,3步耗时太久那么很可能这个同步缓冲区就被重写,此时从库无法找到对应的续传位置它会怎么办?答案是重做1,2,3步!

但因为我们无法解决1,2,3步的耗时因此该从库会永远的进入恶性循环:不停的向主库请求完整数据,结果对主库的网卡造成严重影响。

2 扩容问题

很多时候会出现流量的突发性增长,通常在找到原因之前我们的应急做法就是扩容了。

而根据场景一中的表格,一个20G的redis扩容一个从库需要将近20分钟,在这个紧急的时刻20分钟业务能够容忍吗?可能还没扩好就死翘翘了。

3 网络不好导致从库重做最终引发雪崩

该场景的最大问题是主库与从库的同步中断,而此时很可能从库仍然在接受写入请求,那么一旦中断时间过长同步缓冲区就很可能被复写。此时从库上一次的同步位置已丢失,在网络恢复后虽然主库没有发生变化但由于从库的同步位置丢失了从库必须进行重做,也就是问题一中的1,2,3,4步。如果此时主库内存体积过大那么从库重做速度就会很慢,而发送到从库的读请求就会受到严重影响,同时由于传输的rdb文件的体积过大,主库的网卡在相当长的一段时间内都会受到严重影响。

4 内存越大,触发持久化的操作阻塞主线程的时间越长

Redis是单线程的内存数据库,在redis需要执行耗时的操作时,会fork一个新进程来做,比如bgsave,bgrewriteaof。 Fork新进程时,虽然可共享的数据内容不需要复制,但会复制之前进程空间的内存页表,这个复制是主线程来做的,会阻塞所有的读写操作,并且随着内存使用量越大耗时越长。例如:内存20G的redis,bgsave复制内存页表耗时约为750ms,redis主线程也会因为它阻塞750ms。

解决办法

解决办法当然就是极力减少内存的使用了,一般情况下,我们都是这么做的:

1 设置过期时间

对具有时效性的key设置过期时间,通过redis自身的过期key清理策略来降低过期key对于内存的占用,同时也能够减少业务的麻烦,不需要定期清理了

2 不存放垃圾到redis中

这简直就是废话,但是,有跟我们同病相怜的人么?

3 及时清理无用数据

例如一个redis承载了3个业务的数据,一段时间后有2个业务下线了,那你就把这两个业务的相关数据清理了呗

4 尽量对数据进行压缩

例如一些长文本形式的数据,压缩能够大幅度降低内存占用

5 关注内存增长并定位大容量key

不管是DBA还是开发人员,你用redis,你就必须关注内存,否则,你其实就是不称职的,这里可以分析redis实例中哪些key比较大从而帮助业务快速定位异常key(非预期增长的key,往往是问题之源)

6 pika

如果实在不想搞的那么累,那就把业务迁移到新开源的pika上面,这样就不用太关注内存了,redis内存太大引发的问题,那也都不是问题了。

最后祈祷线上5000个redis实例都不要异常~~~



本文作者:杨艳杰 张恒

来源:51CTO

时间: 2024-09-27 12:57:02

为什么Redis内存不宜过大的相关文章

原理、方法双管齐下,大神带你细解Redis内存管理和优化

以下内容根据直播视频和幻灯片整理而成. 数据结构 通过了解数据结构,就能知道对象性能,边界条件,就自然而然知道如何恰当的使用它们,做业务时就能选到最合适的对象. 上图是Redis最基本的结构体,所有Redis对象都被封装在RedisObject中.最基本的结构代码往往是最精简的.该结构中有5个成员,type 4 比特,encoding也是4比特.从代码得知: Redis的数据类型不超过16种,编码方式不超过16种,且类型跟编码方式不一一对应,一种类型可能有多个编码方式,数据也可以共享. 首先看O

Redis内存使用优化与存储

Redis数据类型  最为常用的数据类型主要有五种:String, Hash, List, Set和SortedSet. redis内部使用一个redisObject对象来表示所有的key和value.redisObject最主要的信息如下图所示:  type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际

谷歌浏览器内存占用过大怎么解决

谷歌浏览器内存占用过大怎么解决   Chrome浏览器可以通过重启释放大量内存,这里教大家一个方便的方法,可以做一个简单的书签来快速重启Chrome浏览器,而且重启后Chrome还能自动恢复刚才浏览的所有标签页,一键搞定! Chrome浏览器释放内存小技巧: 1.在任意标签页使用快捷键Ctrl+D (Windows) / Cmd+D (Mac) ,打开添加书签的页面,然后点击"修改" 2.在网址栏输入:chrome://restart,名字的嘛你随意即可.然后点击底部的保存按钮即可.

Win7系统Installer文件夹占用内存空间太大怎么办

  Installer文件夹是什么? Installer文件夹是Windows Installer 服务的缓存文件夹,用于防止MSI应用程序安装包的缓存数据文件,系统中安装的msi安装格式的程序越多,它的体积就越大,对于硬盘空间有限的情形(例如为虚拟机分配的虚拟硬盘.固态硬盘)来说,鸭梨山大. Installer文件夹可以删除吗? Installer 文件夹下的文件不能随便删除.该文件夹的目的是缓存基于MSI安装包的应用程序安装数据.在应用程序安装.更新.删除时,其中的数据可用于确认旧版本的文件

关于java内存泄露求大神帮忙分析

问题描述 关于java内存泄露求大神帮忙分析 用MAT进行分析但是有点看不懂求大神帮忙分析一下 解决方案 Java内存泄露和分析Java内存泄露分析Java内存泄露问题分析 解决方案二: Details 看看 解决方案三: 你看看你有没有写入到内存里很大的文件 解决方案四: 这是今天重新定位问题的明细图片 解决方案五: 这是相关数据的图片

字节跳动-django实现**.zip包下载报错内存使用过大

问题描述 django实现**.zip包下载报错内存使用过大 django实现**.zip包下载报错内存使用过大 各位朋友们好: 我使用django的功能想实现下载一个大的**.zip包的功能,该包大小差不多1个G 网上查了一些方法:本来是准备用遍历文件目录逐个文件打包的,但是我需要打包的文件很多,用这个方法很慢,而且由于我里面有中文文件,遍历文件路径还会报错.因此我选择了,直接我先把所有文件打包到名叫test.zip中,希望用django实现直接下载test.zip包的功能,但是尝试了好几次,

数据-redis内存溢出有什么好一点的解决办法.

问题描述 redis内存溢出有什么好一点的解决办法. 小弟又来唠叨了, redis里面有什么方法当内存达到限制值,把过期的数据存到硬盘不存到内存,通过这样的方式来释放内存 解决方案 过期的数据redis内存不够的时候会自动清除来释放内存.

Hibernate: org.hibernate.query.list内存消耗过大的问题?

问题描述 使用JProfiler进行性能测试时发现如下情况: 在程式不停的运行中,query.list分配的内存不会被回收.不断创建新的instance. 是多线程运行的程序. 使用Query的方法如下:   public List find(String strhql) {          // TODO Auto-generated method stub            List result = null;          Session session = null;   

低端房产迎租赁小高潮房东提价幅度不宜过大

7月流火,大学毕业生带来的需求让租赁市场迎来了一波小高潮,尤其是低端租赁住宅需求在短时间内大增.不过专家建议,鉴于当前供应充足的现状,低端租赁住宅的房东提价幅度不宜过大,以免难以出租而带来空关损失. 租赁市场迎来新需求 今年毕业的小李选择留在上海,他被一家基金公司录用,过两天就准备到公司报到并正式上班.在上班之前,他要做的第一件事就是找到一个合适的住处.经过多方努力,他和同学在杨浦区合作了一套老公房,面积不大,租金水平也比较适中. 跟小李一样,在2011年毕业的各类毕业生,仅上海预计可达14万人