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 文件都是绝对安全的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值