参考博客:https://javaguide.cn/interview-preparation/teach-you-how-to-prepare-for-the-interview-hand-in-hand.html
一、持久化机制
- 为什么要有持久化?
redis数据都在内存中,一旦宕机数据都会丢失,为了解决这个问题引入了持久化机制。 - 持久化机制分类
它持久化有两种机制:RDB快照,AOF日志。
二、RDB快照
特点:
1.备份方式:RDB是一次全量备份;
2.数据存储:RDB是内存数据二进制序列化形式,在存储上非常紧凑,即体积较小;
3.数据恢复:由于体积小,则恢复数据非常快;
4.启动:redis默认方式。
问题:
由于是全量备份,则每次备份耗时较高且频率会相对低,则会存在大量丢数据问题。(丢数据:1、系统停止2、无意中Redis被kill掉)
缺省情况情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb。
你可以配置Redis的持久化策略:1、例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;2、或者你可以手工调用命令SAVE或BGSAVE。
三、工作原理
. Redis forks.
. 子进程开始将数据写到临时RDB文件中。
. 当子进程完成写RDB文件,用新文件替换老文件。
. 这种方式可以使Redis使用copy-on-write技术(写入时复制)
四、AOF日志
特点:
- 备份方式:AOF连续的增量备份;
- 数据存储:AOF日志存储的是redis服务器顺序指令序列,它在长期的运行中会变的无比庞大;
- 数据恢复:由于AOF体积非常大重放整个AOF非常耗时;
- 启动:手动设置。
问题:
AOF默认是每秒备份一次(除非业务强要求,不然别动),在数据完整性可保证(最多丢1s数据),但是AOF体积可能非常大,数据恢复时重放AOF会非常慢。
五、AOF重写
-
为什么要做AOF重写?
为了解决AOF日志体积大问题,redis提供了bgrewriteaof指令用于对AOF日志进行瘦身。 -
AOF重写原理?
开辟一个子进程对内存进行遍历,转化成一系列redis的操作指令,序列化到新的AOF日志文件中,再将操作期间的增量AOF日志追加到新的AOF上,最后用新的AOF替代旧的AOF,从而大大减小了AOF的体积。 -
具体过程如下图:
六、混合持久化
- 混合持久化解决什么问题?
重启redis时,如果用RDB恢复数据虽然速度快但是会丢失大量的数据,采用AOF重放可以保证数据完整性但是超级慢,为了解决以上2个问题,redis 4.0 带来了一个新的持久化方式—混合持久化。 - 混合持久化设置
aof‐use‐rdb‐preamble yes - 混合持久化原理
AOF在重写时,不再是单纯将内存数据转换为指令命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
总结
- RDB 二进制文件体积小,恢复数据快,但是存在丢大量数据问题;
- AOF redis指令的日志体积大,恢复数据慢,但数据完整性可以保证;
- 混合持久化 结合了RDB和AOF各自优点,恢复数据较快,会有少量数据丢失。
开启AOF或混合持久化需要谨慎,因为它有可能会拖垮redis性能,没有业务的强要求不要开启。
如果有业务要求开启AOF,建议配置为 appendfsync everysec 把数据持久化的刷盘操作,放到后台线程中去执行,尽量降低 Redis 写磁盘对性能的影响。
1、RDB和AOF配合做持久化
RDB bgsave做镜像全量持久化,aof做增量持久化。
因为bgsave会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要aof来配合使用。
在redis实例重启时,会使用bgsave持久化文件重新构建内存,再使用aof重放近期的操作指令来实现完整恢复重启之前的状态。
2、突然机器掉电会怎样?
取决于aof日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。
3、bgsave的原理
fork和cow。fork是指redis通过创建子进程来进行bgsave操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。