redis持久化机制(RDB&AOF)

RDB(Redis DataBase)AOF(Append Only File) 是redis持久化的两种机制。

redis将数据持久化到磁盘流程

  1. 客户端向服务端发送写操作(数据在客户端的内存中)
  2. 数据库服务端接收到写请求的数据(数据在服务端内存中)
  3. 服务端调用write系统调用,将数据往磁盘上写(数据在系统内存的缓冲区)
  4. 操作系统将缓冲区数据转移到磁盘控制器(数据在磁盘缓存中)
  5. 磁盘控制器将数据写到磁盘的物理介质中(数据到磁盘)

对于redis来说,只要完成第三步,就完成了redis数据的可持久化,4-5两步由操作系统来完成。

关于redis的配置都在redis.conf文件中,里面也保存了 RDB 和 AOF 两种持久化机制的配置。

RDB 机制

RDB 机制其实是一个在指定时间间隔内将redis中的数据同步到磁盘中保存的操作,也是默认的持久化方式。这种方式回把内存中的数据以快照的形式写入的二进制文件中,默认文件名为dump.rdb

简单来说,它会把数据以快照的形式保存到磁盘中。

快照:就是把当前时刻的数据拍成一张照片保存下来。

RDB 提供了三种方式来触发RDB 的快照操作:

1. save触发方式

save 是一个阻塞式命令。
该命令会阻塞当前redis服务器,执行save命令来 RDB 的过程中,无法处理其它命令,知道 RDB 结束。

执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。

2. bgsave触发方式

执行该命令时,redis会 fork 出一个子进程去异步进行快照操作,同时主进程还可以响应客户端请求。

不过在 fork 出子进程的阶段,主进程是阻塞的,但 fork 的时间一般很短,基本上redis内部所有的 RDB 操作都采用 bgsave 命令。

3. 自动触发

自动触发是由配置文件来决定的:

①save

用来配置触发redis的 RDB 触发条件。
比如,save m n ,表示m秒内数据集存在n次修改时,触发bgsave

默认配置如下:

#表示900 秒内如果至少有 1 个 key 的值变化,则保存
save 900 1
#表示300 秒内如果至少有 10 个 key 的值变化,则保存
save 300 10
#表示60 秒内如果至少有 10000 个 key 的值变化,则保存
save 60 10000

当你不需要 RDB 持久化时,可以注释掉所有 save 行来停用。

② stop-writes-on-bgsave-error

默认值为yes。
当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。
如果Redis重启了,那么又可以重新开始接收数据了。

③ rdbcompression

默认值是yes。
对于存储到磁盘中的快照,可以设置是否进行压缩存储。

④ rdbchecksum

默认值是yes。
在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

⑤ dbfilename

设置快照的文件名,默认是 dump.rdb

⑥ dir

设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。

总结:

  1. savebgsave 对比
命令savebgsave
IO类型同步异步
阻塞?是(fork和快照)否(fork)
复杂度O(n)O(n)
优点不消耗额外内存不阻塞客户端命令
缺点阻塞客户端命令需要fork,消耗内存
  1. RDB 机制存在的问题

    由于 RDB 在本质上是一个周期性地去备份所有数据,而且周期还是分钟级别的,然后一个服务器每秒要处理的请求是相当多的,在进行快照的时候,所更新的数据无法持久化。
    若当在 RDB 时,发生灾难,这些这期间更新的数据将全部丢失。

AOF 机制

AOF 持久化

RDB 全量备份是相当耗时的,所以无法进行高频备份。
于是,此时redis提供了 AOF 机制,
工作原理就是redis会将收到的写命令都通过write函数追加到文件中,就是记录日志。

当然,它不可能每来执行一条写命令都记录到文件中,每次的磁盘IO都需要消耗性能。

所以,redis会先将需要记录的命令保存在临时缓冲区aof_buf中,然后择机将这些数据批量写入文件。

同时,将临时缓冲区的数据批量写入文件后,操作系统会先将这些数据保存在文件系统的内核缓冲区。

AOF 会通过appendfsync参数配置决定什么时候调用fsync强制同步到磁盘,确保数据不丢失。

总之,AOF流程为:

  1. redis接收写命令并保存到临时缓冲区aof_buf
  2. redis择机(调用beforeSleep函数前,即redis主时间循环结束前)将aof_buf中的数据批量写入到磁盘
  3. 根据appendfsync参数触发fsync同步策略

AOF重写

随着时间推移,AOF 的备份文件越来越大,不仅非常占用硬盘空间,而且难以复制移动、加载分析。

所以,AOF提供了文件重写机制,对备份文件进行压缩。
redis提供了bgrewriteaof命令,会将内存中的数据以命令的方式保存到临时文件中, 同时fork一条子进程来将文件重写。

它是怎么进行文件重写呢?
其实很多中间状态是无用的,只需要把最终的数据状态以命令的形式记录下来。
比如:

  • RPUSH name_list ‘编程技术宇宙’
  • RPUSH name_list ‘帅地玩编程’
  • RPUSH name_list ‘后端技术学堂’
    知道最终数据状态,可以压缩为一条
  • RPUSH name_list ‘编程技术宇宙’ ‘帅地玩编程’ ‘后端技术学堂’

如果在文件重写的过程中,又有写命令进来,就会出现实际数据与重写的内容不一致的情况,这种情况也需要解决。

因此,redis在创建重写子进程的那一刻起,会将这时来的写入命令先保存到 AOF重写缓冲区 中,等到子进程重写 AOF 文件结束后,再将缓冲区的命令写入到新的 AOF 文件中。

最后,替换掉原先臃肿的大文件即可。

AOF fsync的三种触发机制

1. always

同步持久化,每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好。

2. everysec

异步操作,每秒记录 如果一秒内宕机,有数据丢失。redisfsync的默认策略。

3. no

从不同步,由操作系统来决定。

总结:

命令alwayseverysecno
优点不丢失数据每秒一次fsync,丢失一秒的数据不用管
缺点IO开销大丢一秒数据不可控

拓展知识

RDB 机制的优缺点

优势

  1. RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。

  2. 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。

  3. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

劣势

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

AOF 机制的优缺点

优势

  1. AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。

  2. AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。

  3. AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。

  4. AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝 AOF 文件,将最后一条flushall命令给删了,然后再将该 AOF 文件放回去,就可以通过恢复机制,自动恢复所有数据。

劣势

  1. 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大

  2. AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的

  3. 以前AOF发生过bug(阻塞命令BRPop``BLPop曾引起过这样的bug),就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来,虽然这种bug几乎不可能出现,但 RDB 是不会出现这种问题的。

RDB 和 AOF 应该选择哪一个?

一般来说,如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能
如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式:
因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,
除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。因为以上提到的种种原因, 未来我们可能会将 AOF 和 RDB 整合成单个持久化模型。 (这是一个长期计划。)

AOF文件出错了怎么办?

服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。

当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:

为现有的 AOF 文件创建一个备份。
使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复。
$ redis-check-aof --fix
(可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两 个文件之间的不同之处。
重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。

RDB 和 AOF 之间的相互作用

在版本号大于等于 2.4 的 Redis 中, bgsave 执行的过程中, 不可以执行 bgrewriteaof 。 反过来说, 在 bgrewriteaof 执行的过程中, 也不可以执行 bgsave
这可以防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作。

如果 bgsave 正在执行, 并且用户显示地调用 bgrewriteaof 命令, 那么服务器将向用户回复一个 OK 状态, 并告知用户, BGREWRITEAOF 已经被预定执行:

一旦 bgsave 执行完毕, bgrewriteaof 就会正式开始。
当 Redis 启动时, 如果 RDB 持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集, 因为 AOF 文件所保存的数据通常是最完整的。

备份数据

Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建, 就不会进行任何修改。
当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 原子地用临时文件替换原来的 RDB 文件。
这也就是说, 无论何时, 复制 RDB 文件都是绝对安全的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值