Skip to content

Redis持久化 🌟重要

概念

redis是数据内存数据库,而内存中的数据具有易失性,为了防止数据的丢失,需要将数据从内存保存到硬盘,当下一次重启之后就可以将数据从磁盘加载到内存中。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置。

两种形式

  • RDB持久化:将当前数据保存到硬盘(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化),默认的持久化方式。
  • AOF持久化:将每次执行的写命令保存到硬盘(原理是将Reids的操作日志以追加的方式写入文件,类似于MySQL的binlog)。主流持久化方式。

由于AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式,不过RDB持久化仍然有其用武之地。

Redis 提供了不同级别的持久化方式

  • RDB持久化方式 能够在指定的时间间隔能对你的数据进行快照存储.
  • AOF持久化方式 记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.保存每次写的操作到文件末尾
  • 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
  • 你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.

最重要的事情是了解RDB和AOF持久化方式的不同

RDB持久化

基本概念


即在指定目录下生成一个dump.rdb文件。Redis重启会通过加载dump.rdb文件恢复数据。(/var/lib/redis/6379)

触发快照的方式

  • 执行shutdown命令,让服务器关闭,意义不大。
  • 执行flushall命令,清空数据库,意义也不大。
  • 手动执行save(bgsave)触发快照
bash
save 30 2   
# 17:22:45的时候,执行了一次save命令,就会触发快照,也就是dump.rdb文件的修改时间是17:22
# 接下来快速执行两次写命令,但是当时间达到17:23:00的时候,发现dump.rdb的修改时间还是17:22
# 但是当时间递推到17:23:15以后得时候,再查看dump.rdb,会发现dump.rdb的修改时间发生了改变17:23

优缺点

优点

  • 适合大规模数据的恢复,恢复速率是比较快的
  • 如果对数据的完整性与一致性要求不高,可以使用RDB
  • 数据恢复的文件是二进制的

缺点

  • 对数据的完整性与一致性不高,有可能丢失更多的数据
  • 备份时占用内存,因为Redis 在备份时会独立创建一个fork子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍哦),最后再将临时文件替换之前的备份文件。

使用建议

  • 如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
  • RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.

AOF持久化

基本概念

如前面介绍的,AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍,就这么简单。

默认是没有开启AOF持久化方式的,通过设置配置文件可以打开,我们通过配置redis.conf中的appendonly yes就可以打开AOF功能。如果有写操作(如SET等),redis就会被追加到AOF文件的末尾。默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis仍然可以保持很好的处理性能,即使redis故障,也只会丢失最近1秒钟的数据。

重写

因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上,只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。

为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 BGREWRITEAOF命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令; Redis 2.4 则可以自动触发 AOF 重写, 具体信息请查看 配置文件。

Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发

bash
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

bash
set k1 100
incr k1 
//该命令执行100次

set k1 200
-------------------------------------
set k1 200
incr k1
incrby k1 300

set k2 200
set k3 hello 
//...
del k1
del k2
del k3

触发重写的命令BGREWRITEAOF命令

优缺点

优点

  • 数据的完整性与一致性更高
  • 数据的丢失比较小

使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据。

AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题。

Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。

AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL命令,并重启 Redis,就可以将数据集恢复到 FLUSHALL 执行之前的状态。

缺点

  • 数据的恢复速率比较慢
  • 导致文件的大小会比较大

对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。

根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

总结

  • 如果对数据的恢复速率比较快的时候,可以选择rdb,如果需要数据比较完整的时候,可以使用aof
  • 两种持久化的方式是可以同时使用的。
  • 单独使用任何一种持久化的方式都可以启动服务器。
  • 如果aof是唯一的持久化方式,并且aof文件损坏了,那么服务器是不能进行启动的。但是可以使用命令进行修复

image-20240802180803001

思考

两种持久化方式如何选择?

如何选择?没有最好的,只有最适合的,根据各自的特点灵活选择。

两种持久化方式能不能同时使用?如果能,redis重启时按照哪个文件的内容恢复数据。

能同时使用,重启时先按照AOF文件的内容回复数据

如果开启了aof方式,并且aof文件损坏,redis能否启动成功?

启动不成功,如果AOF文件损坏redis服务程序会启动失败。

aof文件如果损坏,怎么处理?

AOF文件损坏,可以用redis-check-aof修复 redis-check-aof --fix 文件名

如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。(只做缓存)

如果对数据的安全性要求非常高的话,那么最好一起开启,如果能允许分钟内的数据丢失的话,就选择RDB。

如果数据需要时常备份的话,最好开启RDB。

两者可以同时开启,也可以只使用一个,但是如果都开启的话,Redis重启时只会加载AOF文件来恢复数据。