持久化流程

  • 客户端向服务端发送写操作(数据在客户端的内存中)。
  • 数据库服务端接收到写请求的数据(数据在服务端的内存中)。
  • 服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
  • 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
  • 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。

redis提供了RDB和AOF两种持久化存储方案

RDB

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb

对于RDB来说,提供了三种机制:save、bgsave、自动化

save

该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。

bgsave

执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。

具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。

自动化

自动触发是由我们的配置文件来完成的。

对比

命令 save bgsave
io类型 同步 异步
阻塞 阻塞 阻塞(fork阶段)
复杂度 O(n) O(n)
优点 不消耗额外内存 不阻塞客户端命令
缺点 阻塞客户端命令 需要额外内存fork

优缺点

优点

  1. RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
  2. 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
  3. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

缺点

RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。

AOF

redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录

AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写

重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似

三种触发方式

  1. 每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
  2. 每秒同步everysec:异步操作,每秒记录 如果一秒内宕机,有数据丢失
  3. 不同no:从不同步
命令 always everysec no
优点 不丢数据 每秒一次fsync 不管数据
缺点 IO开销大,磁盘TPS几百 可能丢1秒数据 不可控

优缺点

优点

  1. AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
  2. AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
  3. AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
  4. AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。

缺点

  1. 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
  2. AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的

参考

  1. 详解Redis中两种持久化机制RDB和AOF