RDB持久化

RDB 快照是怎么实现的? | 小林coding

Redis有两种持久化方式:AOF日志和RDB快照

  • AOF 文件的内容是操作命令;
  • RDB 文件的内容是二进制数据。

RDB 快照记录某一个瞬间的内存数据,记录的是实际数据,而 AOF 文件记录的是命令操作的日志,而不是实际的数据。

RDB优点:在 Redis 恢复数据时, RDB 恢复数据的效率会比 AOF 高些,因为直接将 RDB 文件读入内存就可以,不需要像 AOF 那样还需要额外执行操作命令的步骤才能恢复数据。

Redis 的快照是全量快照,也就是说每次执行快照,都是把内存中的「所有数据」都记录到磁盘中。所以可以认为,执行快照是一个比较重的操作,如果频率太频繁,可能会对 Redis 性能产生影响。如果频率太低,服务器故障时,丢失的数据会更多。

通常可能设置至少 5 分钟才保存一次快照,这时如果 Redis 出现宕机等情况,则意味着最多可能丢失 5 分钟数据。

RDB 快照的缺点:在服务器发生故障时,丢失的数据会比 AOF 持久化的方式更多,因为 RDB 快照是全量快照的方式,因此执行的频率不能太频繁,否则会影响 Redis 性能,而 AOF 日志可以以秒级的方式记录操作命令,所以丢失的数据就相对更少。

生成RDB快照

有两个命令

  • save 命令,在主线程生成 RDB 文件,由于和执行操作命令在同一个线程,所以如果写入 RDB 文件的时间太长,会阻塞主线程
  •  bgsave 命令,会创建一个子进程来生成 RDB 文件,这样可以避免主线程的阻塞

RDB 文件的加载工作是在服务器启动时自动执行的,没有提供专门用于加载 RDB 文件的命令。

Redis 还可以通过配置文件的选项来实现每隔一段时间自动执行一次 bgsave 命令,默认会提供以下配置:

只要满足上面条件的任意一个,就会执行 bgsave,分别指:

  • 900 秒之内,对数据库进行了至少 1 次修改;
  • 300 秒之内,对数据库进行了至少 10 次修改;
  • 60 秒之内,对数据库进行了至少 10000 次修改。

执行快照时数据的修改

执行 bgsave 过程中,依靠写时复制技术,Redis 主线程依然可以继续处理操作命令

创建 bgsave 子进程后,子进程共享父进程的所有内存数据,可以直接读取主线程(父进程)里的内存数据,并将数据写入到 RDB 文件。

主线程(父进程)对这些共享的内存数据也都是只读操作,那么,主线程(父进程)和 bgsave 子进程相互不影响。

当主线程(父进程)要修改共享数据里的某一块数据(比如键值对 A)时,就会发生写时复制,于是这块数据的物理内存就会被复制一份(键值对 A'),然后主线程在这个数据副本(键值对 A')进行修改操作。与此同时,bgsave 子进程继续把原来的数据(键值对 A)写入到 RDB 文件

bgsave 快照过程中,如果主线程修改了共享数据,发生了写时复制后,RDB 快照保存的是原本的内存数据,而主线程刚修改的数据,是没办法在这一时间写入 RDB 文件的,只能交由下一次的 bgsave 快照。所以 Redis 在使用 bgsave 快照过程中,如果主线程修改了内存数据,不管是否是共享的内存数据,RDB 快照都无法写入主线程刚修改的数据,因为此时主线程(父进程)的内存数据和子进程的内存数据已经分离了,子进程写入到 RDB 文件的内存数据只能是原本的内存数据。

需要注意:

  • 进程写入到 RDB 文件的内存数据只有原本的内存数据,如果系统恰好在 RDB 快照文件创建完毕后崩溃了,那么 Redis 将会丢失主线程在快照期间修改的数据。
  • 在 Redis 执行 RDB 持久化期间,刚 fork 时,主进程和子进程共享同一物理内存,但是途中主进程处理了写操作,修改了共享内存,于是当前被修改的数据的物理内存就会被复制一份。在极端情况下,如果所有的共享内存都被修改,则此时的内存占用是原先的 2 倍。所以,针对写操作多的场景,我们要留意下快照过程中内存的变化,防止内存被占满了。

RDB和AOF结合

RDB优点:

  • 与 AOF 方式相比,通过 rdb 文件恢复数据比较快。
  • RDB 是二进制压缩文件,占用空间小,便于传输(传给 slaver)、数据备份等。
  • 通过 RDB 进行数据备份,由于主进程 fork 子进程来进行持久化,所以对 Redis 服务器性能影响较小。

RDB缺点:

  • 如果服务器宕机的话,采用 RDB 的方式会造成某个时段内数据的丢失,比如我们设置 5 分钟达到 1000 次写入就同步一次,那么如果还没达到触发条件服务器就死机了,那么这个时间段的数据会丢失。
  • 使用 save 命令会造成服务器阻塞,直到数据同步完成才能接收后续请求。
  • 使用 bgsave 命令在 fork 子进程时,如果数据量太大,fork 的过程也会发生阻塞,另外,fork 子进程会耗费内存。

AOF优点:

  • AOF 设置为每秒保存一次,则最多丢 2 秒的数据。数据丢失相对 RDB 来说更少。
  • AOF 写入文件时,对过期的 key 会追加一条 del 命令,当执行 AOF 重写时,会忽略过期 key 和 del 命令。

AOF缺点:

  • 生成的日志文件太大,即使通过 AOF 重写,文件体积仍然很大
  • 恢复数据的速度比 RDB 慢。

RDB 比 AOF 的数据恢复速度快,但是快照的频率不好把握:

  • 如果频率太低,两次快照间一旦服务器发生宕机,就可能会比较多的数据丢失;
  • 如果频率太高,频繁写入磁盘和创建子进程会带来额外的性能开销。

混合持久化同时具备RDB恢复速度快和AOF丢失数据少的优点

注意:混合持久化工作在 AOF 日志重写过程

混合持久化过程:在AOF重写日志时,fork出的重写子进程先将此时的快照以RDB的方式写入AOF文件,主线程的写操作会以AOF的方式写入重写缓冲区,重写缓冲区里的增量命令会以 AOF 方式写入到 AOF 文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。

使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据

这样,重启 Redis 加载数据的时候,由于前半部分是 RDB 内容,这样加载的时候速度会很快

加载完 RDB 的内容后,才会加载后半部分的 AOF 内容,这里的内容是 Redis 后台子进程重写 AOF 期间,主线程处理的操作命令,可以使得数据更少的丢失

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值