AOF机制
redis默认不开启AOF机制,可以通过redis.config配置来开启AOF
AOF机制是指,redis在每一个写命令执行成功后,会将其记录到日志。每个命令后记录的机制有几个好处:
- 不用额外的开销检查命令是否合法
- 不会阻塞当前写
不过AOF机制记录日志不是每个命令立刻就落盘,而是先写到AOF缓冲区,然后再调用write写到AOF文件,此时文件内容并没有落到磁盘,二是在内核的page cache,由内核决定什么时候将AOF文件中的内容写入磁盘。有3种:(内核通常先将数据复制到内核缓冲区中,然后排入队列)
- Always:每次写后调用fsync()
- Everysec:每秒调用fsync()
- No:不调用
AOF有重写机制来避免AOF文件过大,重写机制使用的是后台子线程bgrewriteaof,调用fork()函数创建一个新的AOF文件(不在原先的AOF文件是为了避免重写失败影响原本的日志)
子线程和父线程虽然共享资源,但是会有写时复制,避免了锁的开销(为什么不用子线程)。
同时,重写期间新的命令会同时写到重写缓冲区,重写结束后,子进程给父进程发送信号,父进程将重写缓冲区合并到aof缓冲区,并修改新的AOF文件名将旧的覆盖。
RDB机制
AOF机制的缺点是恢复起来太慢了,redis是单线程处理。因此redis还有一个持久化机制——RDB快照。redis默认开启RDB快照。
RDB快照通过save或者bgsave来记录当下的内存数据内容,是一个全量数据。save在主进程上运行,bgsave在子进程上运行。redis可以设置快照的拍摄频率,但是因为RDB是全量快照,所以频率太高会降低redis性能。
bgsave同样采用写时拷贝技术,在fork()时如果主进程没有修改,则bgsave保存的是相同的一份数据。如果主进程修改了,那么内核会触发写时复制操作,因此新写的数据不会保存进快照中。所以开启一次快照后再新写数据遇上宕机会丢失。
redis可以采用RDB+AOF结合的机制,将RDB后的新命令用AOF存起来,一起保存到新的AOF文件中。