聊聊Redis的持久化策略(redis持久化机制有哪些)
mhr18 2024-10-23 11:35 32 浏览 0 评论
作者的其他平台:
| 知乎:https://www.zhihu.com/people/1024-paper-96
| github:https://github.com/JiangXia-1024?tab=repositories
| csdn:https://blog.csdn.net/qq_41153943
| 掘金:https://juejin.cn/user/651387938290686
| 公众号:1024笔记
本文大概6061字,建议阅读13分钟
前言
前面的一篇文章分布式缓存中间件Redis入门对分布式缓存中间件做了一些简单的介绍,其实关于分布式中间件的内容远不止那些。通过前面的介绍我们知道Redis是一个内存数据库,数据保存在内存中,内存的数据变化是很快的,也容易发生丢失。所以Redis提供了持久化的机制。
这篇文章就来介绍Redis的持久化。
什么是持久化?
对于持久化某度某科的解释是:
持久化是将程序数据在持久状态和瞬时状态间转换的机制。通俗地讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)
所以对于持久化狭义的理解就是: “持久化”仅仅指把域对象永久保存到数据库中;可以广义地理解为:“持久化”包括和数据库相关的各种操作(持久化就是将有用的数据以某种技术保存起来,将来可以再次取出来应用,数据库技术,将内存数据一文件的形式保存在永久介质中(磁盘等)都是持久化的例子)。
数据持久化对象的基本操作有:保存、更新、删除、加载、查询等。
保存:把域对象永久保存到数据库。
更新:更新数据库中域对象的状态。
删除:从数据库中删除一个域对象。
加载:根据特定的OID,把一个域对象从数据库加载到内存。
查询:根据特定的查询条件,把符合查询条件的一个或多个域对象从数据库加载内存中。
为什么需要持久化
通过前面的介绍我们知道Redis的数据全部在内存里,所以万一出现突然出现故障发生宕机,那么保存在内存中的数据就会全部丢失,因此必须有一种机制来保证Redis的数据不会因为故障而丢失,这种机制就是Redis的持久化机制。
除此之外使用数据持久化还有以下好处:
1、持久化技术封装了数据访问细节,为大部分业务逻辑提供面向对象的API。
2、程序代码重用性强,即使更换数据库,只需要更改配置文件,不必重写程序代码。
3、业务逻辑代码可读性强,在代码中不会有大量的SQL语言,提高程序的可读性。
4、持久化技术可以自动优化,以减少对数据库的访问量,提高程序运行效率。
5、松散耦合,使持久化不依赖于底层数据库和上层业务逻辑实现,更换数据库时只需修改配置文件而不用修改代码。
如何持久化
对于数据的持久化主要有以下的五个过程:
1、客户端向服务端发送操作(数据在客户端的内存中)。
2、数据库服务端接收到写请求的数据(数据在服务端的内存中)。
3、服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
4、操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
5、磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。
这5个过程是在理想条件下一个正常的保存流程,但是在大多数情况下,我们的机器都会有各种各样的故障,这里划分了两种情况:
(1)Redis数据库发生故障,只要在上面的第三步执行完毕,那么就可以持久化保存,剩下的两步由操作系统替我们完成。
(2)操作系统发生故障,必须上面5步都完成才可以。
在这里只考虑了保存的过程可能发生的故障,其实保存的数据也有可能发生损坏,需要一定的恢复机制,篇幅有限这里不进行展开。
Redis对于数据的持久化同样需要通过以上五个步骤,在Redis4.x中对于数据的持久化方案主要有三种策略机制:
1、RDB(Redis DataBase)
2、AOF(Append Only File)
3、混合型方案
RDB机制
RDB机制是Redis里面默认提供的一套持久化技术方案,专门用于保证内存中的数据被写入到磁盘里面去,是指在指定的时间间隔内将内存中的数据集快照写入磁盘。快照是数据存储的某一时刻的状态记录,可以理解为把当前时刻的数据保存下来,由于是某一时刻的快照,那么快照中的值要早于或者等于内存中的值。这种方式是通过修改相应的redis.conf来实现的,默认的文件名为dump.rdb。在我们安装了redis之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。
比如:
redis.config中的语句主要是用于将数据持久化在redis的dump.rdb文件里面,然后每一次开启redis的时候都会将里面的数据重新加载,进行数据恢复。dump.rdb的存放位置由下边的dir来标识。
前面说了RDB机制是通过把某个时刻的所有数据生成一个快照来保存,既然是快照那么就应该有一种触发机制,来触发快照的功能。对于RDB来说,提供了三种机制来触发快照,分别是:save、bgsave、自动触发机制。
rdb里面并不是单纯将数据直接存储起来,而是通过一种特定的lzf压缩方式来实现的:
这个配置开关最好打开,默认是开启的,否则会导致rdb文件过大,占用磁盘空间。
触发rdb存储机制的条件有两种:
1、手动触发:
1、执行save指令:这是一种阻塞式指令,阻塞当前redis服务器,直RDB过程完成为止。如果内存比较大会造成redis长时间阻塞,所以线上禁止使用。具体流程可以总结如下:
2、执行bgsave命令:执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,时间一般很短,具体和实例数据大小有关系。具体流程可以总结如下:
2、自动触发:
除了执行上面的两种命令手动触发之外,redis还存在以下4种方式自动触发RDB的持久化机制。
1、使用save相关配置,如“save m n” 表示m秒内数据集存在n次修改时,自动触发bgsave。也可以同时配置多个条件,只要其中一个达标就触发。
config文件中save机制的配置如下:
save <指定时间间隔> <执行指定次数更新操作> (默认是save 900 1)
复制代码
可以理解为指定的秒内如果进行了指定次数的更新操作,就会将数据存储到dump.rdb文件中去。
2、主从复制时,从节点执行全量复制操作,主节点自动执行bgsave生成RDB文件并发送给从节点;
3、执行debug reload命令时重新加载redis
4、默认情况下执行shutdown命令时,如果没有开启aof持久化则自动执行bgsave
每项技术都会有一定的优点和缺点,RDB的优缺点可以总结如下:
优点:
1、RDB适合大规模的数据恢复。
2、RDB是一个紧凑压缩的二进制文件,占用的内存比较小,代表数据在某一个时间点的快照。非常适合备份,全景复制。比如每三个小时执行bgsave备份,并把RDB文件上传到备份服务器中,用于防止Redis服务器不可恢复性问题。
3、RDB恢复数据速度快于AOF的方式。
4、RDB 可以最大化 redis 的性能。父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
5、RDB 非常适用于灾难恢复(disaster recovery),因为它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心。
缺点:
1、RDB 在服务器故障时容易造成数据的丢失。RDB允许通过修改配置来控制持久化的频率。但是,因为RDB文件需要保存整个数据集的状态,所以它是一个比较繁重的操作,如果频率太频繁,会对Redis性能产生一定的影响。所以一般可以设置至少5分钟才保存一次快照,这时如果 Redis 出现宕机等情况,也就意味着最多可能丢失5分钟数据。所以数据的完整性和一致性不高。
2、备份时会占用内存。因为Redis 在备份时会独立创建一个子进程并且采用的是 copy-on-write 的方式,在 Redis 执行 RDB 持久化期间,如果 client 写入数据很频繁,那么将增加 Redis 占用的内存,最坏情况下,内存的占用将达到原先的2倍。刚 fork 时,主进程和子进程共享内存,但是随着主进程需要处理写操作,主进程需要将修改的页面拷贝一份出来,然后进行修改。极端情况下,如果所有的页面都被修改,则此时的内存占用是原先的2倍。
3、如果数据比较大时,备份的时候会比较耗时RDB 保存时使用 fork 子进程进行数据的持久化时,如果数据比较大的话,fork 可能会非常耗时,造成 Redis 停止处理服务N毫秒。如果数据集很大且 CPU 比较繁忙的时候,停止服务的时间甚至会到一秒。
4、同上因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高,所以RDB方式数据没办法做到实时持久化/秒级持久化。
5、因为RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,所以存在老版本Redis服务无法兼容新版RDB格式的问题。
AOF机制
前面说了虽然RDB能够作为redis的持久化进行数据的备份,但是也存在一些不足。所以为了弥补RDB的缺点,aof机制应势而出。aof的全称是append only file,它是以独立日志的形式来将每一次写操作都进行记录,追加到相应的文件中去。Redis重启的时候会根据日志文件的内容从前到后执行一次达到数据恢复的目的。前面说到RDB有个缺点就是数据备份的实时性比较低,所以AOF的主要作用是解决了数据持久化的实时性,目前AOF已经是Redis持久化的主流。
在conf文件中同样有对于aof的配置:
appendonly:默认值为no,因为r前面说过Redis 默认使用的是rdbd的持久化方式,如果想要开启 AOF 持久化方式,需要将 appendonly 修改为 yes。
appendfilename :指的是aof文件名,默认是"appendonly.aof"
appendfsync:aof持久化策略的配置,可取的值有三种:always、everysec和no。
设置为always时,会极大消弱Redis的性能,因为这种模式下每次write后都会调用fsync立马将数据写入磁盘进行持久化(Linux为调用fdatasync)。虽然性能差,但是安全性是最高的。
设置为no时,则write后不会有fsync调用,由操作系统自动调度刷磁盘,直接写入aof的内存缓冲区,性能是最好的。
设置为everysec时,最多每秒调用一次fsync,这种模式性能并不是很糟糕,一般也不会产生毛刺,这归功于Redis引入了BIO线程,所有fsync操作都异步交给了BIO线程。这也是推荐的策略模式,就如同配置说明上说的:If unsure, use "everysec"(如果不确定就是使用everysec)。
它们三个可以总结为:
策略 | 写回时机 | 优点 | 缺点 |
Always | 同步写回 | 数据基本不会丢失,可靠性好 | 每个命令都要写入磁盘,性能较差 |
No | 系统控制 | 性能好 | 安全性差,宕机时丢失数据较多 |
Everysec | 每秒写回 | 性能中等 | 宕机时丢失一秒内的数据 |
AOF里触发该机制的条件可以在conf文件里面进行配置:
当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。
配置参数:
auto-aof-rewrite-min-size 64mb
复制代码
表示aof文件要达到一定体积才会进行重写
auto-aof-rewrite-percentage 100
复制代码
表示当aof文件大小增长了100%才会触发重写
重写的原理
aof在进行重写处理的时候,会额外开辟一个bgrewriteaof线程,将原先的aof文件数据拷贝到一个临时文件进行处理,最后再覆盖原先文件。AOF文件重写过程与RDB快照bgsave工作过程有点相似,都是通过fork子进程,由子进程完成相应的操作,同样的在fork子进程简短的时间内,redis是阻塞的。具体过程如下图所示:
相比于rdb而言,aof的数据备份效率更高,但是在数据恢复的时候其性能却远远不如rdb高效。
混合型策略
重启 Redis 时,如果采用rdb来恢复内存状态,会丢失大量数据。
如果使用 aof,性能相对rdb来说要慢很多,这样在Redis数据很大的情况下,启动的时候时间消耗比较大。
混合型策略是Redis4.0开始添加的新的混合型持久化方案。混合型方案就是将前面的RDB持久化方案以及AOF持久化方案结合。
混合持久化同样也是通过bgrewriteaof完成的,不同的是当开启混合持久化时,fork出的子进程先将共享的内存副本全量的以RDB方式写入aof文件,然后在将aof_rewrite_buf重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。可以简单的理解为:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据,可以理解为:
这样做的好处是可以结合 rdb 和 aof 的优点, 快速加载同时避免丢失过多的数据,而缺点是 aof 里面的 rdb 部分就是压缩格式不再是 aof 格式,可读性差。
混合持久化默认关闭的,可以通过aof-use-rdb-preamble配置参数控制,yes则表示开启,no表示禁用,默认是禁用的。
aof-use-rdb-preamble yes # yes:开启,no:关闭
复制代码
如果开启了混合策略,那么在启动redis时依然优先加载aof文件进行数据恢复,而aof文件加载可能有两种情况如下:
1、如果aof文件开头是rdb的格式, 先加载 rdb内容再加载剩余的 aof。
2、如果aof文件开头不是rdb的格式,直接以aof格式加载整个文件。
虽然混合策略是rdb和aof结合的,但是它有优点同样也还有一定的缺点:
优点:
混合持久化结合了RDB持久化 和 AOF 持久化的优点, 由于绝大部分都是RDB格式,加载速度快,同时结合AOF,增量的数据以AOF方式保存了,数据更少的丢失。
缺点:
兼容性差,一旦开启了混合持久化,在4.0之前版本都不识别该aof文件。
同时由于前部分是RDB格式,阅读性较差。
总结
以上主要介绍了redis对数据进行持久化的三种策略,分别是:RDB、AOF以及基于其两种方案的混合型持久策略。这三种策略都有自己的优点和缺点,实际使用中可以根据实际的场景和需求进行合理的选择。
最后欢迎关注公众号:1024笔记,免费获取海量学习资源(涵盖视频、源码、文档)!
相关推荐:
- SpringBoot入门:使用IDEA和Eclipse构建第一个SpringBoot项目
- SpringBoot入门:SpringBoot整合Freemarker和Thymeleaf模板
- 聊聊Spring中的AOP(笔面试必问)
- 聊聊Spring中IOC的基本原理
- Pycharm一直卡在connecting to console的解决办法「图文步骤」
- Drop、Truncate和Delete究竟怎么删除
- Java注解(Annotation)的基本原理以及实现自定义注解
- 如何同步Idea上的项目到远程Github上
- Tomcat的安装、配置以及如何部署web项目
- 分布式缓存中间件Redis入门
- 笔面试题系列:请说说Memcache与Redis的区别
- Vue.Js中过滤器的简单使用
- 笔面试题系列:请说说Equals和==的区别
- 如何在Vue.js中对时间格式化
- SQL语言:DDL、DML、DQL、DCL详解
相关推荐
- Redis合集-使用benchmark性能测试
-
采用开源Redis的redis-benchmark工具进行压测,它是Redis官方的性能测试工具,可以有效地测试Redis服务的性能。本次测试使用Redis官方最新的代码进行编译,详情请参见Redis...
- Java简历总被已读不回?面试挂到怀疑人生?这几点你可能真没做好
-
最近看了几十份简历,发现大部分人不是技术差,而是不会“卖自己”——一、简历死穴:你写的不是经验,是岗位说明书!反面教材:ד使用SpringBoot开发项目”ד负责用户模块功能实现”救命写法:...
- redission YYDS(redission官网)
-
每天分享一个架构知识Redission是一个基于Redis的分布式Java锁框架,它提供了各种锁实现,包括可重入锁、公平锁、读写锁等。使用Redission可以方便地实现分布式锁。red...
- 从数据库行锁到分布式事务:电商库存防超卖的九重劫难与破局之道
-
2023年6月18日我们维护的电商平台在零点刚过3秒就遭遇了严重事故。监控大屏显示某爆款手机SKU_IPHONE13_PRO_MAX在库存仅剩500台时,订单系统却产生了1200笔有效订单。事故复盘发...
- SpringBoot系列——实战11:接口幂等性的形而上思...
-
欢迎关注、点赞、收藏。幂等性不仅是一种技术需求,更是数字文明对确定性追求的体现。在充满不确定性的网络世界中,它为我们建立起可依赖的存在秩序,这或许正是技术哲学最深刻的价值所在。幂等性的本质困境在支付系...
- 如何优化系统架构设计缓解流量压力提升并发性能?Java实战分享
-
如何优化系统架构设计缓解流量压力提升并发性能?Java实战分享在高流量场景下。首先,我需要回忆一下常见的优化策略,比如负载均衡、缓存、数据库优化、微服务拆分这些。不过,可能还需要考虑用户的具体情况,比...
- Java面试题: 项目开发中的有哪些成长?该如何回答
-
在Java面试中,当被问到“项目中的成长点”时,面试官不仅想了解你的技术能力,更希望看到你的问题解决能力、学习迭代意识以及对项目的深度思考。以下是回答的策略和示例,帮助你清晰、有说服力地展示成长点:一...
- 互联网大厂后端必看!Spring Boot 如何实现高并发抢券逻辑?
-
你有没有遇到过这样的情况?在电商大促时,系统上线了抢券活动,结果活动刚一开始,服务器就不堪重负,出现超卖、系统崩溃等问题。又或者用户疯狂点击抢券按钮,最后却被告知无券可抢,体验极差。作为互联网大厂的后...
- 每日一题 |10W QPS高并发限流方案设计(含真实代码)
-
面试场景还原面试官:“如果系统要承载10WQPS的高并发流量,你会如何设计限流方案?”你:“(稳住,我要从限流算法到分布式架构全盘分析)…”一、为什么需要限流?核心矛盾:系统资源(CPU/内存/数据...
- Java面试题:服务雪崩如何解决?90%人栽了
-
服务雪崩是指微服务架构中,由于某个服务出现故障,导致故障在服务之间不断传递和扩散,最终造成整个系统崩溃的现象。以下是一些解决服务雪崩问题的常见方法:限流限制请求速率:通过限流算法(如令牌桶算法、漏桶算...
- 面试题官:高并发经验有吗,并发量多少,如何回复?
-
一、有实际高并发经验(建议结构)直接量化"在XX项目中,系统日活用户约XX万,核心接口峰值QPS达到XX,TPS处理能力为XX/秒。通过压力测试验证过XX并发线程下的稳定性。"技术方案...
- 瞬时流量高并发“保命指南”:这样做系统稳如泰山,老板跪求加薪
-
“系统崩了,用户骂了,年终奖飞了!”——这是多少程序员在瞬时大流量下的真实噩梦?双11秒杀、春运抢票、直播带货……每秒百万请求的冲击,你的代码扛得住吗?2025年了,为什么你的系统一遇高并发就“躺平”...
- 其实很多Java工程师不是能力不够,是没找到展示自己的正确姿势。
-
其实很多Java工程师不是能力不够,是没找到展示自己的正确姿势。比如上周有个小伙伴找我,五年经验但简历全是'参与系统设计''优化接口性能'这种空话。我就问他:你做的秒杀...
- PHP技能评测(php等级考试)
-
公司出了一些自我评测的PHP题目,现将题目和答案记录于此,以方便记忆。1.魔术函数有哪些,分别在什么时候调用?__construct(),类的构造函数__destruct(),类的析构函数__cal...
- 你的简历在HR眼里是青铜还是王者?
-
你的简历在HR眼里是青铜还是王者?兄弟,简历投了100份没反应?面试总在第三轮被刷?别急着怀疑人生,你可能只是踩了这些"隐形求职雷"。帮3630+程序员改简历+面试指导和处理空窗期时间...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)