Redis 持久化机制探究(AOF 和 RDB)

Redis的数据全都在内存中,如果宕机了,那后果将不堪设想。因此必须有一种机制来保障redis的数据不会因为故障而丢失  —— 即 redis的持久化机制

分类

一种是快照(RDB) —— 全量备份。内存数据的二进制序列化形式,存储上非常紧凑

另一种是AOF日志 —— 增量备份。数据修改的指令记录文本,随着时间推移,占用的空间会变得很大。这会导致redis重启时加载AOF指令重放的过程非常缓慢。因此需要定期进行AOF重写

 

持久化

快照原理(RDB)

redis主要是单线程程序,这个线程既要响应客户端的请求又要进行文件IO(内存快照),后者会严重拖垮服务器性能。那怎么办呢?

Redis 使用操作系统的多进程 COW(Copy On Write) 机制来实现快照持久化

Redis 在持久化时会调用 glibc 的函数fork产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚刚产生时,它和父进程共享内存里面的代码段和数据段。这时你可以将父子进程想像成一个连体婴儿,共享身体。这是 Linux 操作系统的机制,为了节约内存资源,所以尽可能让它们共享起来。在进程分离的一瞬间,内存的增长几乎没有明显变化

子进程做数据持久化,它不会修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化写到磁盘中。但是父进程不一样,它必须持续服务客户端请求,然后对内存数据结构进行不间断的修改

这个时候就会使用操作系统的 COW 机制来进行数据段页面的分离。数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对这个复制的页面进行修改。这时子进程相应的页面是没有变化的,还是进程产生时那一瞬间的数据

即使父进程在进行各种更改性的操作,但由于COW机制,子进程看到的内存里的数据在进程产生的一瞬间就凝固了,再也不会改变,这也是为什么 Redis 的持久化叫「快照」的原因

AOF原理

AOF 日志存储的是 Redis 服务器的顺序指令序列,AOF 日志只记录对内存进行修改的指令记录

Redis 会在收到客户端修改指令后,进行参数校验进行逻辑处理后,如果没问题,就立即将该指令文本存储到 AOF 日志中,也就是先执行指令才将日志存盘

AOF重写

Redis 提供了 bgrewriteaof 指令用于对 AOF 日志进行瘦身。其原理就是开辟一个子进程对内存进行遍历转换成一系列 Redis 的操作指令,序列化到一个新的 AOF 日志文件中。序列化完毕后再将操作期间发生的增量 AOF 日志追加到这个新的 AOF 日志文件中,追加完毕后就立即替代旧的 AOF 日志文件了,瘦身工作就完成了

Redis 4.0 混合持久化

重启redis时,由于使用rdb来恢复内存状态会丢失大量数据,因此很少使用。但AOF重放,在redis实例很大的情况下,需要耗费大量的时间

4.0版本为了解决这个问题,引入了混合持久化方式 —— 将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小

 

混合持久化

于是,redis重启的时候,可以先加载rdb的内容,再重放后面的增量aof。效率得到大大提升

实践

笔者此时的环境是   CentOS Linux release 7.7.1908 (Core)   +  redis 5.0.7

在 redis.conf 中

appendonly 默认是关闭的,此时使用的是rdb方式;当开启aof时,会默认使用aof方式

aof-use-rdb-preamble yes   表示开启混合持久化 ,此时AOF数据以 REDIS 开头

参考

Redis持久化和数据恢复的坑

评论或私信站长


  1. #该文章暂时没有评论