Redis持久化

206 阅读2分钟

Redis的持久化有两种方式

  • 快照:(RDB snapshot)一次全量备份,二进制,存储上很紧凑,Redis从硬盘恢复不需要重放,而是直接二进制映射到内存,比较快。
  • AOF:连续的增量备份,在长期使用中,日志会变得庞大。Redis重启就会从AOF日志中读取,并回放,这个时间会很漫长,所以需要定期为进行AOF重写,给AOF日志瘦身。


快照的原理

Redis是单线程的系统,在处理先上请求的同时还需要进行内存快照,内存快照需要Redis必须进行文件IO操作,可文件操作是不能多路复用的API。

这就意味着,RDB的快照会严重拖累系统性能,而且在take snapshot的同时,先上请求还在不停修改数据,redis为了解决这个问题,使用了CopyOnWrite机制,下面介绍copyOnWrite的原理。

CopyOnWrite的原理是Redis调用glibc函数fork一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚产生的时候,它的内存和父进程完全复用,当父进程修改某个内存的时候,就把这个内存copy出来(确切来说是把这个内存所处的内存页copy出来,也就是4K的内存copy出来),然后在副本上修改(也是是copy on write的由来)。这样一来,子进程的内存是不会发生改变的,可以安心在另一个进程中进行读取并写入文件。

RDB快照的问题是快照的周期设多长,如果过于频繁,系统的CPU也会吃紧,虽然是在不同的进程。

AOF原理

AOF日志是Redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录,所以Redis可以通过依次执行这些记录,达到重放的目的。

随着Redis的运行,AOF文件会变得很庞大,如果一一重放会很耗时间,所以需要瘦身(AOF重写),将可以合并的command进行合并。

写入AOF的函数是glibc中的fsync(int fd)函数,他负责将指定文件的内容强制从内存刷到硬盘上,只要Redis实时调用fsync就不会丢失AOF日志,但这很慢。有些运维的做法是将Redis配置成每1s写一次,有些运维就直接不开AOF,看具体应用场景。比如如果是纯缓存,就可以不开AOF

Redis4.0 混合持久化

Redis4.0引入机制将RDB和AOF结合,原理是周期性地进行RDB快照,快照之后,AOF存放的日志就只需要包含快照之后的日志,这样从硬盘恢复的时候,先从快照整体映射到内存,再回放AOF中记录的操作。