Redis持久化

  2019-9-28 


Redis 的持久化机制有两种,第一种是快照,第二种是 AOF 日志

快照(RDB)

快照是一次全量备份。快照是内存数据的二进制序列化形式,在存储上非常紧凑。
快照方式采用操作系统的多进程 COW(Copy On Write) 机制来实现快照持久化。(因为快照化遍历数据,需要进行IO操作,而Redis 单线程IO的,这样就没法处理客户端请求了;而且由于数据还会被客户端修改;所以直接本地化是行不通的)
COW机制先fork一个子进程,与父进程共享资源;子进程完全负责持久化工作,它遍历数据;此时当父进程的数据被修改的时候,由COW机制来进行数据段页面的分离:数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对这个复制的页面进行修改。这时子进程相应的页面是没有变化的,还是进程产生时那一瞬间的数据。

缺点:RDB由于保存一次是要保存整个数据库,那么很可能就会出现保存这段时间出现数据丢失;而且当修改量大的时候,RDB相对比较占内存资源

AOF

AOF 日志是连续的增量备份。AOF 日志记录的是内存数据修改的指令记录文本。AOF 日志在长期的运行过程中会变的无比庞大,数据库重启时需要加载 AOF 日志进行指令重放,这个时间就会无比漫长。所以需要定期进行 AOF 重写,给 AOF 日志进行瘦身
Redis 提供了 bgrewriteaof 指令用于对 AOF 日志进行瘦身。其原理就是开辟一个子进程对内存进行遍历转换成一系列 Redis 的操作指令(相当于减少冗余操作指令),序列化到一个新的 AOF 日志文件中。序列化完毕后再将操作期间发生的增量 AOF 日志追加到这个新的 AOF 日志文件中,追加完毕后就立即替代旧的 AOF 日志文件了,瘦身工作就完成了。
fsync:AOF 日志是以文件的形式存在的,当程序对 AOF 日志文件进行写操作时,实际上是将内容写到了内核为文件描述符分配的一个内存缓存中,然后内核会异步将脏数据刷回到磁盘的。
这就意味着如果机器突然宕机,AOF 日志内容可能还没有来得及完全刷到磁盘中,这个时候就会出现日志丢失。
Linux 的glibc提供了fsync(int fd)函数可以将指定文件的内容强制从内核缓存刷到磁盘。只要 Redis 进程实时调用 fsync 函数就可以保证 aof 日志不丢失(即操作了立即写到日志)。但是 fsync 是一个磁盘 IO 操作,非常慢,所以需要综合考量fsynv频率。

缺点:占用磁盘空间大;根据fsync策略,速度可能会慢于RDB

混合持久化

在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放。
这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。


且听风吟