0%

Redis持久化

Redis支持两种持久化手段,下面分别进行总结

  1. RDB(Redis DataBase):将当前Redis数据库中的所有数据以二进制的形式存储在.rbd文件中,也就是状态备份
  2. AOF(Append Only File):将写操作持久化在AOF文件中,也就是状态机备份

RDB

RDB机制将当前Redis存储的所有KV对存储在二进制文件中,持久化的触发时机有两个:

  1. 显式调用savebgsave

  2. 满足配置文件中的持久化条件

    • 在过去的xxx秒内,若写入操作超过xx个,则进行RDB持久化

为了避免写入RDB阻塞Redis响应客户端的写入请求,Redis通过fork()生成子进程负责执行RDB生成操作。

Linux中的fork()操作基于copy-on-write(COW)机制,将子进程的内存复制推迟到了父进程执行写入操作。

  • COW机制的fork():创建子进程时,子进程与父进程共享正文段,开辟新空间复制父进程的数据段,队,栈。
  • Linux中的fork():创建子进程时,只为子进程创建虚拟空间,与父进程共享物理空间,当父进程修改对应物理空间数据库,再为子进程开辟空间复制数据。

Redis的后台RDB机制基于Linux中的fork()copy-on-write(COW),因此其生成的RDB文件保存的是发起RDB持久化时刻的Rdis数据库状态

AOF

AOF(Apeend Only File)通过记录变更持久化数据库状态,变更包括sethsetdel等数据库写入操作,其实实现机制类似于Mysql中的redo log

  • 每次写入操作执行后,写入到位于内存的AOF缓冲区aof_buf

  • 刷新时机由配置文件参数appendfsync控制(和Mysql一毛一样

    1. no:只写入文件,但是不调用文件系统刷新接口fsync()
    2. everysec:写入文件,若距离上次调用fsync()超过一秒,则调用
    3. always:每次写入后调用fsync()

由于AOF采用了记录操作的思路实现持久化,相较于RDB,带来了两个新问题

  1. 重启无法像RDB文件一样,直接加载到内容中即可
    • Redis采取“伪客户端”逐个执行操作的方式,实现启动时的状态还原
  2. 随着Redis执行的操作越来越多,AOF文件大小也会越来越大,重启重新执行的时间也会过长
    • Redis使用异步AOF重写机制,实现AOF文件的缩小
    • AOF重写机制:基于当前状态构建生成当前数据库状态的操作,生成新的AOF文件(根据结果反推过程替代真正的过程),例如sadd a,sadd b,s add c->sadd a b c
    • 对应命令为BGREWRITEAOF
      除主动调用外,当AOF文件大于配置文件中设置大小时,后台自动启动AOF重写操作。

RDB vs AOF

RDB和AOF都是Redis提供的实现持久化的手段,两者的区别主要在于:

  1. RDB是对Redis状态的持久化,AOF是对Redis操作的持久化,因此AOF的粒度更细
  2. RDB以二进制形式存储,AOF存储的是一个一个修改操作,因为RDB文件更小
  3. 在Redis重新启动时,RDB形式的备份只需要加载,AOF则需要逐个操作读取执行

上述区别导致了AOF更适合数据持久性要求更高的应用场景,RDB更适合做数据备份以及持久性要求较低的应用场景。

参考

  1. Redis persistence
  2. Redis设计与实现
  3. [详细讲解Linux内核写时复制技术COW机制](