Redis持久化

持久化是什么

持久化即将内存中的数据写入硬盘,目标是为了之后重用数据或做数据同步。

Redis支持3钟持久化方式

3种持久化方式分别是什么

RDB:通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。可以对快照进行备份,可以复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构,提高性能),可以原地保留等服务器重启时使用

会阻塞主线程吗:
save命令会阻塞,bgsave会fork出一个子进程,不会阻塞Redis主线程,默认选项为bgsave

AOF:比RDB实时性更好,Redis6.0版本前默认不开启,可以通过appendonly yes开启。

开启后,每执行一条会更改Redis中数据的命令,
Redis就会将该命令写入AOF缓冲区server.aof_buf中,再写入AOF文件,
最后再根据持久化方式的配置来决定何时将系统内核缓存区的数据同步到硬盘,到此,持久化成功。

RDB和AOF的混合持久化:

AOF持久化如何实现

整体流程:客户端发送写命令、Redis执行写操作命令(在内存中)、Redis记录写操作命令到日志(位于硬盘)

1.AOF日志

是什么:保存了Redis执行过的写操作命令的文本文件(不保存读操作命令,因为没意义)
查看:cat命令
先执行再保存的好处:①避免检查命令是否正确的开销②不会阻塞当前写操作命令的执行
先执行再保存的风险:①执行完未写入宕机导致丢失②可能阻塞下一个写操作命令的执行
综上,我们可以得出AOF日志写回硬盘的时机很重要,引出第二点——写回策略

2.三种写回策略

写入日志的细化流程:执行写操作命令、命令追加到server.aof_buf缓冲区、I/O系统调用write()、将aof_buf缓冲区数据拷贝到内核缓冲区page cache、内核发起写操作、写入硬盘
redis.conf配置文件中的appendfsync配置项目中有以下3种参数可选:

Always,每次写操作命令执行完毕,同步将AOF日志数据写回硬盘
Everysec,每次写操作命令执行完毕,先将AOF命令写入AOF文件的内核缓冲区,然后每隔1s将缓冲区里的内容写回到硬盘
No,意味着不由Redis控制写回硬盘的时机,由操作系统决定何时将内核缓冲区内容写回硬盘
由于主进程阻塞减少数据丢失是对立问题,这三个策略无法同时完美解决这两个问题。

3.AOF重写机制

用来避免AOF日志文件越来越大,在重写时读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到新的AOF文件,读完之后用新的AOF文件替换现有的
巧妙之处:

4.AOF后台重写

因为AOF重写很耗时间,为了避免阻塞主进程,我们用后台子进程bgrewriteaof来完成重写。
好处:

子进程如何拥有主进程一样的数据副本?
主进程通过fork系统调用生成bgrewriteaof子进程时,操作系统会把主进程的页表复制一份给子进程,页表中记录着虚拟地址和物理地址的映射关系,而不会复制物理内存,即两者的虚拟空间不同,但对应同一个物理空间,从而共享父进程的物理内存数据,节约物理内存资源,但此时页表对应的页表项会标记该物理内尺寸的权限为只读,当父/子进程向这个内存发起写操作时,CPU会触发写保护中断(由于违反权限),操作系统会在写保护中断处理函数里面进行物理内存的复制,并重新设置其内存映射关系,将父子进程的内存读写权限设置为可读写,最后才对内存进行写操作,这个过程称之为写时复制
简而言之就是,在发生写操作时,操作系统才复制物理内存。
而重写子进程只会对这个内存进行读操作,所以主进程依然可以正常处理命令。
问题1.如果重写过程中主进程修改了已经存在的key-value,就会发生写时复制,但这里只会复制主进程修改的物理内存数据,没修改的部分还是与子进程共享的。

5.总结

RDB快照

大key对Redis持久化的影响