为什么需要持久化?
Redis数据都存在内存里,也就是说如果你不小心踢了电源,或者电脑突然宕机,数据就全部OVER了。所以就得有一种机制保证Redis的数据不会因为各种各样的故障丢失。
Redis的持久化机制
有两种机制,第一种RDB快照,对数据做一次全量备份,本质是内存数据的二进制序列化形式;第二种AOF日志,连续的增量备份,记录的是内存数据修改的指令记录文本。
RDB原理
Redis是单线程程序,也就意味着这个线程要同时负责多个客户端套接字的并发读写操作和内存数据结构的逻辑读写。
而且RDB内存快照要求Redis必须进行文件IO操作,这操作会严重拖累服务器性能。
所以Redis使用操作系统的COW(copy on write)机制来实现快照持久化。
Redis在持久化时会调用glibc的函数fork产生一个子进程,快照持久化就在子进程里进行。子进程刚刚产生时,和父进程(也就是Redis处理客户端请求的进程)共享内存里的代码段和数据段。
子进程做数据持久化,不会修改现有的内存数据结构,只对数据结构进行遍历读取,然后序列化写到磁盘。而父进程持续服务客户端请求,对内存数据结构进行不断的修改。
这时候COW机制会进行数据段页面的分离。简单说,就是父进程对其中一个操作系统的页面(4k每个)进行修改时,会将被共享的页面复制一份,对这个复制出来的页面进行修改,这就不会影响到子进程正在持久化的页面,但数据还是进程产生时的数据。
AOF原理
AOF日志只记录对内存进行修改的指令记录,也就是说保存的并不是数据。
Redis在收到客户端修改指令后,进行参数校验、逻辑处理,没问题的话(比如指令错误等),就立即将指令文本存储到AOF日志中(先执行指令再保存)。
Redis提供了bgrewriteaof指令对AOF日志瘦身,原理就是再开一个子进程对内存进行遍历,转换成Redis操作指令,序列化到一个新AOF日志。序列化完再将操作期间发生的指令追加到新AOF日志中。
fsync函数可以将AOF日志强制从内核缓存刷到磁盘,一般1s刷一次,如果执行一条指令刷一次,那性能会很低。
混合持久化
也就是同时开启RDB和AOF。将rdb文件的内容和增量AOF日志文件存放在一起。AOF不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志。
这样在Redis重启的时候,先加载RDB内容,再重放AOF日志,效率就会提升不少。