Redis作为基于内存的缓存数据库,就会存在断电即失的问题,所以数据的持久化是非常重要的。Redis随着版本升级迭代,持久化技术也在不断的升级,(从最开始的RDB,到的Redis1.1版本加入AOF,3.0版本支持RDB和AOF的混合使用,7.0版本也同样做了升级-后续研究)目前主要持久化RDB和AOF两种。
1、Fork原理
fork是操作系统的一个系统调用函数,原则是读时共享写时拷贝,主要作用是用来创建一个新的进程,也就是子进程。子进程被创建时会copy父进程所有信息。其中就包括虚拟地址(指向物理地址,用来在内存中找数据),也就是说此时父进程和子进程有这独立的虚拟地址空间,且指向相同的物理地址空间。
fork子线程方式,节省了重新拷贝一份数据的内存空间,同时在结合copy-on-write策略,实现了极少的内存copy成本完成父子进程内存独立(父子进程修改数据对方不会察觉,也就是内存数据拷贝功能),基本原理如下:
此时父进程对虚拟地址1的元素进行了修改,会在内存中copy一份元素,并将父进程的虚拟地址指向这个元素物理地址,而子进程依旧指向原来的物理地址。这就是Copy-on-write原则:
RDB内存快照
RDB是Redis最早使用持久化技术,简单的说就是不同的时间点,将Redis存储的数据生产快照存储在磁盘上。详细的说,可以通过配置save规则,告知Redis在达到规则时间点后,开始持久化操作,Redis主线程会通过系统调用fork创建一个子进程,被fork出来的子进程,它copy了Redis主进程相关信息,其中就包括虚拟空间地址,同时fork通过copy-on-write原则,实现了Redis主进程和子进程内存数据的写隔离,那子进程会异步的将日志写入到磁盘中,这种技术的好处是,通过写时copy这样的小成本,避免了大量内存数据拷贝带来的内存和效能问题。缺点就是可能在子进程写入磁盘时,发生宕机这样的问题,由于数据是在内存中的,所以会产生一部分数据丢失。
优点:
1、RDB存储是二进制数据文件,磁盘占用很小,数据恢复速度快,也非常方便做数据的传输,比如做容灾就很适合。
2、RDB数据是紧凑型的,每次持久化都是全量的数据,所以可以通过一些方式做数据备份,比如每天备份一份数据出来。
3、RDB是通过fork形式异步的写入磁盘,同时结合copyonwrite原则,不会影响主进程正常使用,最大化的提高了redis性能。
缺点:
1、因为可能是一段时间处理一次,当发生宕机的时候,可能存在一部分数据丢失。
2、如果数据量非常大的时候,fork过程也会有更大的时间消耗。
AOF只追加操作文件
因为RDB并不是耐久的,在发生宕机之后,可能存在部分数据丢失,所以在1.1版本之后新增了AOF持久化方式,也就是追加的方式写入操作到文件。可以通过配置appendfsync,来配置追加规则,默认是每秒追加一次操作到文件中。当开启AOF模式之后,每当输入一个写入的操作指令,这个命令首先会被append到AOF缓存区,然后根据fsync规则同步追加到AOF文件末尾。这样在重启redis时候,就会通过读取和执行AOF中的指令恢复数据。
BgRewriteaof AOF重写机制
因为AOF是一个不断追加的过程,当长时间持久化之后,AOF文件会越来越庞大,为了尽可能的减小AOF文件,Redis提供的AOF的重写机制,主要是用来重写AOF文件中的指令,做精化处理,比如incr了k1 10次,其实就等于是set k1 10 ,所以重写之后就AOF就成了set k1 10。
因为Redis是单线程处理数据的,所以为了重写过程中不打断客户端操作的情况下,Redis提供了gbrewriteaof命令进行重写操作,它和RDB原理类似巧妙了利用了写时复制机制,通过fork的方式创建子进程完成重写工作,主要重写方式有多种:
1、直接读取内存中的数据,生成最小指令,
2、读取原AOF配置,进行语义分析重写,大致原理如下:
AOF优点:
1、AOF数据是非常耐久的,它默认每秒一次的频率同步,即使在宕机的情况下,最多也只会丢失一秒的数据。
2、AOF数据因为宕机等问题损坏后,可以通过redis-check-aof工具进行修复。
3、AOF支持指令重写功能,因为利用了写时复制机制,不会影响主进程的正常使用,即使宕机情况下,原AOF数据也不会丢失。
4、AOF文件时redis文本协议格式存储的,可读性强,可以通过修改AOF文件完成某些场景下一些版本恢复。
RDB-AOF混合
因为RDB会产生数据丢失,但是它文件小,恢复速度快,而AOF文件文件大,但是数据不容易丢失。Redis为了更好的利用各自优点,在Redis4.0版本时,支持RDB-AOF混合持久化模式,其实也是对AOF的增强。
补充:Redis在启动的时候,同时开启了AOF和RDB时,会优先加载AOF文件,如果AOF不存在,则取加载RDB。
混合模式也是在重写时触发的,不同的是重写是子线程会优先将内存中的数据按照RDB的形式写入到AOF的头部,以Redis头标识,后面新增的写入操作,一样的流程append到AOF文件的尾部。这样一来,AOF整体的文件就会变得很小,同时数据也同样很耐久。
原图地址: