当前位置: 代码网 > it编程>数据库>Redis > Redis持久化解读

Redis持久化解读

2025年01月11日 Redis 我要评论
redis 是内存级数据库,其数据存储在内存中,因此能够提供快速的读写速度。但我们知道内存属于掉电易失存储器,一旦断电,存储在内存中的数据就会丢失。在服务器重启和 redis 服务重启后数据都会丢失。

redis 是内存级数据库,其数据存储在内存中,因此能够提供快速的读写速度。但我们知道内存属于掉电易失存储器,一旦断电,存储在内存中的数据就会丢失。

在服务器重启和 redis 服务重启后数据都会丢失。因此 redis 提供了三种持久化方式:rdb(快照持久化),aof(追加文件持久化),混合持久化(混合使用 aof 日志和内存快照)。其中aof 文件的内容是操作命令,rdb 文件的内容是二进制数据。

rdb快照

rdb快照是一种将redis数据库状态保存到磁盘上的机制,redis提供了两个命令:save , bgsave。

这两个命令实际上都会生成一份rdb文件,rdb存储了执行命令时的 redis 的所有数据,在 redis 启动时,会自动加载rdb文件恢复数据redis并没有手动加载rdb文件的命令

save与bgsave

save 命令是在主线程下执行,由于和执行操作命令在同一个线程,所以如果写入 rdb 文件的时间太长,会阻塞主线程。

bgsave 命令会创建一个子进程执行 save 命令,主进程不会阻塞。

redis可以通过配置文件的选项来实现每隔一段时间自动执行一次 bgsava 命令:

save <seconds> <changes>
  • <seconds>:自上次保存后经过的时间(以秒为单位)。
  • <changes>:在这个时间段内至少有多少个键被改变。

使用示例: 上次快照以来有 60 秒并且至少有 1000 个键被改变,则自动执行 bgsave。

save 60 1000

我们可以设置多个 save ,只要有一个条件满足就会执行 bgsave。

save 900 1
save 300 10
save 60 10000

bgsave 会先 fork 创建出子进程,在 linux 中 fork 创建出的子进程会复制父进程的页表,与父进程共享一份物理内存。

这种方式减少了创建子进程时的性能损耗,从而加快创建子进程的速度,避免主进程阻塞。创建子进程后,子进程只读,同时将数据存储在 rdb 文件中。

当执行命令的主线程内存数据也都是只读操作时,主线程和 bgsave 子进程相互不影响。当主进程对内存数据修改时会触发中断,中断处理程序会申请一份物理内存重新映射到修改的虚拟内存,这个过程叫做写时拷贝

因此,当主进程执行写操作时,对数据的修改不会影响到子进程,子进程持久化的仍是执行 fork 命令时刻的数据。 因此会产生数据丢失。

在极端情况下,如果所有的共享内存都被修改,则此时的内存占用是原先的 2 倍。所以,针对写操作多的场景,我们要留意下快照过程中内存的变化,防止内存被占满了。

rdb优缺点

rdb优点:

  • 快速恢复: rdb 文件是二进制格式,可以非常快速地加载到内存中,实现redis服务的快速启动。
  • 数据备份: rdb 文件可以很容易地被复制到其他服务器或备份存储中,适合于进行数据备份和灾难恢复。
  • 空间紧凑: 由于rdb文件只包含最终的数据,而不是每一条写命令,所以通常比aof文件更紧凑。
  • 减少i/o操作: 相比于aof持久化,rdb不需要记录每一条写操作命令,因此减少了i/o操作。
  • 适合大规模数据恢复: 由于rdb文件包含了数据集的全量快照,适合于大规模数据的恢复。

rdb缺点:

  • 数据丢失风险:如果两次快照之间redis发生故障,那么这段时间内的数据将丢失。
  • 数据完整性不高:rdb无法保证数据的完整性和一致性。
  • 阻塞:尽管 bgsave 是在后台异步执行的,但在生成rdb文件时,如果数据集非常大,仍然可能会短暂地阻塞主线程。
  • 不适合高频率写操作的场景:在写操作非常频繁的场景,会频繁生成rdb快照对性能产生影响。

aof日志

aof日志持久化并不是直接保存 redis 中的数据,而是记录redis中执行的所有写操作命令。每当redis执行一个写操作命令,该命令会被追加到aof文件中。

在 redis 中 aof 持久化功能默认是不开启的,需要我们修改 redis.conf 配置文件中的以下参数

  • appendonly yes:开启aof持久化。
  • appendfilename "appendonly.aof":指定aof文件的名称。

redis 会先执行命令,执行命令成功后再将命令记录到 aof 日志中,如果先写入 aof 文件还需要检查命令是否执行成功,如果命令执行失败还需要额外操作。先执行命令也保证了aof 不会阻塞当前写操作命令的执行(但可能会阻塞下一个命令的执行),因为当写操作命令执行成功后,才会将命令记录到 aof 日志。

aof持久化,会先将命令写入内存缓冲区中。这个内存缓冲区称为 aof 缓冲区。然后再通过 wirte系统调用写入到磁盘上的 aof 文件。但 wirte写入实际上是将数据拷贝到内核缓存区,由内核决定何时进行磁盘io。如果系统宕机,而缓冲区数据没有写入磁盘,这部分数据就会丢失。

aof写回策略

redis可以通过fsync或fdatasync系统调用来请求操作系统将内核缓存区中的数据强制刷新到磁盘上。

aof提供了三种写回策略: always ,everysec , no。

  • always:每次写操作命令执行完后,同步将 aof 日志数据写回硬盘。即每次执行后都调用 fsync。
  • everysec :每次写操作命令执行完后,先将命令写入到 aof 文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘,即每秒执行一次 fsync 。
  • no: 不由 redis 控制写回硬盘的时机,转交给操作系统控制写回的时机,也就是每次写操作命令执行完后,先将命令写入到 aof 文件的内核缓冲区,再由操作系统决定何时将缓冲区内容写回硬盘。即不执行 fsync 。

这三种策略各有优缺点, always 可靠性最强性能较差,no 性能最强可靠性最差,everysec则更为折中。大家可以根据自己的需要选择策略。

aof重写

aof日志是一个文件,随着执行的写操作命令越来越多,文件的大小会越来越大。如果 aof 文件过大必然会影响性能。因此 redis 提供了 aof重写机制。

当 aof 文件的大小达到一定阈值时,redis 会触发 aof 重写过程。这个阈值可以通过配置设置。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
  • auto-aof-rewrite-percentage:指定 aof 文件大小相对于上一次重写后大小的增长百分比,当超过这个百分比时,redis 将触发 aof 重写。
  • auto-aof-rewrite-min-size: 这个配置项指定了 aof 文件的最小大小,只有当 aof 文件的大小超过这个值时,auto-aof-rewrite-percentage 指定的百分比阈值才会生效。

什么是重写?aof 文件记录了每一个写操作命令,如果记录了对同一数据的多个操作,实际上只有最后一个操作是有意义的,其他操作都是冗余的。aof 重写机制通过创建一个新的 aof 文件来解决这个问题,新文件只包含恢复当前数据集所需的最小命令集合。

在重写时 redis 会通过 fork() 系统调用创建一个子进程,这个子进程与父进程共享相同的内存空间。子进程会遍历 redis 数据库中的所有键,并生成一系列可以恢复这些数据的 redis 命令,同时将这些命令写入到一个临时的 aof 文件中。

重写完成后,子进程会用新的 aof 文件替换旧的 aof 文件,并更新 aof 文件的文件名。

在重写过程中,主进程并不会阻塞而是继续处理客户端请求,同时将执行后的写命令追加到 「aof 缓冲区」与「aof 重写缓冲区」。

当重写完成时,会向主进程发送一条信号,主进程收到该信号后,会调用一个信号处理函数,该函数会做以下工作:

  • 将 aof 重写缓冲区中的所有内容追加到新的 aof 的文件中。
  • 新的 aof 的文件进行改名,覆盖现有的 aof 文件。

然后主进程会继续接收命令并执行,重写也就此完成。

aof优缺点

aof优点

  • 数据安全性高: aof 记录了所有写操作,可以提供更好的数据恢复保证。
  • 数据完整性: aof 能够保证即使在 redis 异常终止的情况下,也不会丢失任何已持久化的写操作。

aof缺点:

  • 磁盘空间使用: aof 文件可能会比 rdb 文件大,因为它记录了所有的写操作命令。
  • 性能影响: 频繁的磁盘i/o操作可能会影响 redis 的性能。
  • 数据恢复速度: 由于 aof 文件可能包含大量的命令,数据恢复速度会比 rdb 慢。

混合持久化

我们可以看到rdb与aof各有优缺点:rdb 恢复速度快,aof 丢失数据少?redis 4.0 引入了一种新的持久化方式,称为混合持久化,它结合了 rdb和 aof持久化的优点。

我们可以通过配置文件开启混合持久化:

aof-use-rdb-preamble yes

当开启了混合持久化时,在 aof 重写时,重写子进程会先将与主线程共享的内存数据以 rdb 方式写入到 aof 文件,然后主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以 aof 方式写入到 aof 文件,写入完成后通知主进程将新的含有 rdb 格式和 aof 格式的 aof 文件替换旧的的 aof 文件。

当 redis 重启时,它会首先加载 rdb 文件快速恢复数据状态。 然后,redis 会执行保存在 aof 文件中的写操作命令(这里的内容是 redis 后台子进程重写 aof 期间,主线程处理的操作命令。),恢复到最新的数据状态。

混合持久化的主要优点是结合了 rdb 和 aof 的优点,提供了更快的数据恢复速度和更少的数据丢失风险。在 aof 重写过程中,redis 确保了数据的完整性和一致性,同时优化了磁盘空间的使用。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com