持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情
Redis 是一个基于内存的数据库,所有数据都是存储在内存中。当 Redis 服务器关机或其他一些异常情况,都会导致存储在内存中的数据丢失。而 Redis 为了解决这种情况的发生,提供了持久化存储的功能
RDB 持久化
RDB 持久化会对 Redis 中的数据进行周期性的持久化,生成一份快照文件,存放在配置文件声明的目录下面的 dump.rdb 文件中。在 Redis 配置文件中可以通过配置 dir 属性来指定持久化文件存放目录。触发 RDB 持久化的过程分为手动触发和自动触发。 接下来我们来学习 RDB 如何进行数据的持久化。
➡️ RDB 持久化原理
-
RDB 持久化的流程
将 Redis 在内存中的数据定时
dump到磁盘上,实际操作过程是fork一个子进程,先将数据写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。下面是 RDB 简单执行流程图:
➡️ RDB 持久化实现
-
通过命令触发 RDB(即手动触发)
a. 通过
save命令触发(同步、阻塞),也就是说save命令执行完毕后才能执行后续的其他命令操作。对于内存比较大的实例会造成长时间的阻塞,线上环境不建议使用。127.0.0.1:6379> save OK 127.0.0.1:6379>b. 通过
bgsave命令触发(异步、非阻塞),bgsave命令是 fork 一个专门 save 的子进程,RDB 的持久化过程由子进程负责,完成后自动结束。其中阻塞是发生在 fork 阶段,一般时间很短(微秒级别)。127.0.0.1:6379> bgsave Background saving started 127.0.0.1:6379> -
通过配置文件触发 RDB(即自动触发)
自动触发,就是通过对 Redis 的配置文件
redis.conf中相关选项的修改,当达到某个配置好的条件后,自动生成 RDB 文件,其内部使用的是bgsave命令。a. 可以在 Redis 配置文件
redis.conf中找到如下内容:# save 3600 1 # save 300 100 # save 60 10000✨ 说明:如果 3600 秒内有 1 个 key 发生了变化,生成一份快照文件;如果在 300 秒内有 100 个 key 发生了改变,生成一份快照文件;如果在 60 秒内有 10000 个 key 发生了改变,生成一份快照文件。这里是 Redis 6.2.6 版本,官方建议配置的最佳参数值,默认这些是注释掉的。
b. 可以在 Redis 配置文件
redis.conf中找到 RDB 文件的配置信息,如下所示:# 默认文件名(可以自行指定) dbfilename dump.rdb # 默认文件保存位置(可以自行指定) dir ./ # 假如 bgsave 执行中发生错误,是否停止写入,默认是 yes,表示出错,就停止写入。 stop-writes-on-bgsave-error yes # 是否使用压缩 rdbcompression yes # 是否进行数据的校验 rdbchecksum yes
➡️ RDB 持久化的优缺点
-
优点
a. RDB 是一个紧凑压缩的二进制文件,代表 Redis 在某个时间点上的数据快照,全量备份,便于数据的传输。
b. 适合大规模的数据恢复。如果服务器宕机了,不要删除 RDB 文件,重启会自动从指定的目录下读取 RDB 文件,并且数据恢复的速度远大于 AOF 方法。
-
缺点
a. 时效性差,容易造成数据的不完整性。由于 RDB 不能实时备份,当某个时间段 Redis 服务出现异常,内存数据丢失,这段时间的数据无法恢复。
b. RDB 采用加密的二进制格式保存,可能存在新老版本不兼容问题。
AOF 持久化
AOF 持久化会记录服务器执行的所有写操作命令,并在 Redis 重启的时候,通过回访 AOF 文件来还原数据集,文件使用 append-only 的默认,所有操作都会追加到文件的末尾。当 AOF 文件体积超出保存数据集状态的情况下,会进行一个重写(rewrite)操作,确保文件不会太大。通常情况下,AOF 文件保存的数据集会比 RDB 文件保存的数据集更完整。
接下来我们来学习 AOF 如何进行数据的持久化。
➡️ AOF 持久化原理
-
AOF 持久化流程
将 Redis 的操作日志以文件追加的方式写入文件,只记录写、删除操作,查询操作不会记录(类似于 MySQL 的 Binlog 日志)。下面是 AOF 简单执行流程图:
➡️ AOF 持久化实现
-
开启 AOF 功能
默认情况下 AOF 持久化是关闭的,通过以下配置开启 AOF 持久化:
appendonly yes✨ 说明:
redis.conf默认是appendonly no,表示 AOF 持久化是关闭的。开启后,会在文件存储目录下面生成一个appendpnly.aof文件,开启了 AOF 之后,Redis 重启的时候,会优先通过 AOF 进行数据恢复。 -
设置保护模式(即 AOF 的 fsync 策略)
打开 AOF 的持久化机制之后,Redis 每接收到一条命令,就会写入日志文件中,然后每隔一定时间再 fsync 一下。可以通过配置以下内容来配置 AOF 的 fsync 策略:
appendfsync everysec✨ 说明:这里 AOF 的 fsync 策略的属性值有 3 个可以配置(下面中的
write操作是指将数据写到os cache,save操作是指将os cache中数据写到磁盘):always:每执行一个命令保存一次。这种模式下,每执行一个命令 ,write和save都会被执行,且save操作会阻塞主进程。性能会变得比较差,但是可以确保说每一条数据都不会丢失。everysec:每秒钟保存一次。这种模式下,save原则上每隔一秒钟就会执行一次,具体的执行周期与文件写入、保存时,Redis 所处的状态有关,此模式下save操作由后台子线程调用,不会引起服务器主进程的阻塞。这个最常用,生产环境下一般都使用这种策略,性能很高。no:只执行write操作,save操作会被略过,只有在 Redis 被关闭、AOF 功能被关闭、系统的写缓存被刷新(如缓存已被写满)这三种情况,save操作才会被执行,但是这三种情况都会引起 Redis 主进程阻塞。这种策略,会让我们的数据不可控,因为无法预知操作系统什么时候会把数据刷到磁盘。
-
关于 AOF 持久化在
redis.conf配置文件中可以找到以下相关内容,进行配置:# 此选项为 AOF 功能的开关,默认为“no”,通过“yes”来开启 AOF 功能 appendonly yes # 指定 AOF 文件名称(可以自定义) appendfilename appendonly.aof # 备份文件存放路径(此参数同样适用于指定RDB备份文件存放路径) dir ./ # 三种备份策略(三者只需要开启以一个即可) appendfsync everysec
➡️ AOF 文件重写(rewrite)
-
AOF 文件重写的原因
Redis 中的数据是有限的,很多数据可能会自动过期,也有可能会被用户删除,但是这些操作都会被 AOF 文件记录下来,所以有可能存在 AOF 文件越来越大的情况,意思就是说,重建数据集根本不需要执行所有 AOF 记录的命令,为了处理这种情况,Redis 提供了一种 rewrite 策略。
-
重写的基本流程
a. Redis 会 fork 一个子进程。
b. 子进程基于当前内存中的数据,构建日志,开始往一个新的临时 AOF 文件中写入日志。
c. Redis 主进程,接收到 client 的写操作,在内存中写入日志,同时新的日志也继续写入旧的 AOF 文件。
d. 子进程完成新的日志文件之后,Redis 主进程将内存中的新日志再次追加到新的 AOF 文件中。
e. 用新的日志文件替换旧的日志文件。
-
重写 AOF 文件的两种方式
a. 手动重写:在 Redis 2.4 之前是需要手动执行
bgrewriteaof命令来进行重写 AOF 文件。b. Redis 2.4 版本之后提供了自动 rewrite 的操作。我们可以配置 rewrite 的策略。
# AOF 文件容量的增长率 auto-aof-rewrite-percentage 100 # AOF 文件的最低容量,就是当前文件的大小大于此值时,就会进行重写。当然这只是其中一个条件。 auto-aof-rewrite-min-size 64mb✨ 说明:这两个参数的意思是,最少 AOF 文件需要达到 64mb 才会进行重写,重写了之后,当检测到当前的 AOF 文件增长幅度大于 100%,也就是 64mb,即当前的 AOF 文件大小为 128mb 的时候,就会自动触发对 AOF 进行重写操作。
-
AOF 破损文件的修复
如果 AOF 文件破损了,可以使用
redis-check-aof --fix filename命令来修复破损的 AOF 文件,比如下面示例:redis-check-aof --fix appendonly.aof
➡️ AOF 持久化的优缺点
-
优点
a. 拥有更高的数据可用性,数据持久化最完整。
b. 日志文件采用
append-only模式,没有任何磁盘寻址的开销,性能非常高,即使文件损坏了,也可以通过 Redis 提供的工具进行修复。c. 提供
rewrite机制,当日志过大时,Redis 以append-only模式不断将修改的日志写入老的磁盘文件,同时 Redis 还会创建一个新的文件用于记录此期间有哪些命令被执行。 -
缺点
a. 同一份数据,通常 AOF 会比 RDB 文件更大,AOF 开启后,支持的写 QPS 会比 RDB 的低,因为 AOF 一般设置为每秒 fsync 一次日志文件,其次在数据恢复的时候,会比较慢,做冷备不太适合。
RDB 和 AOF 的对比
➡️ AOF 和 RDB 的区别
| 命令 | AOF | RDB |
|---|---|---|
| 启动优先级 | 高 | 低 |
| 体积 | 大 | 小 |
| 恢复速度 | 慢 | 快 |
| 数据安全性 | 由策略决定 | 丢数据 |
| 轻重 | 轻 | 重 |
➡️ 持久化方式的选择
-
如何选择持久化方式
a. 不要仅仅使用 RDB 方式,因为那样有可能会导致丢失较多数据。
b. 不要仅仅使用 AOF 方式,因为使用 AOF 进行数据恢复速度较慢,而且使用 RDB 生成快照的方式更加健壮,可以避免 AOF 这种复杂的备份和恢复机制的 bug。
c. 综合使用 AOF 和 RDB 两种持久化机制,用 AOF 保证数据不丢失,作为数据恢复的第一选择;用 RDB 来做不同程度的冷备,在 AOF 文件丢失或者不可用的情况下,可以使用 RDB 来进行数据恢复。
➡️ 两种持久化方式的数据恢复方案
-
数据恢复方案
a. 如果是 Redis 进程挂掉,那么重启 Redis 进程即可,直接基于 AOF 日志文件恢复数据。x
b. 如果是 Redis 进程所在机器挂掉,那么重启机器后,尝试重启 Redis 进程,尝试直接基于 AOF 日志文件进行数据恢复,如果 AOF 文件破损,那么用
redis-check-aof fix filename命令修复。c. 如果 Redis 当前最新的 AOF 和 RDB 文件出现了丢失/损坏,那么可以尝试基于该机器上当前的某个最新的 RDB 数据副本进行数据恢复。
d. 在数据完全丢失的情况下,基于 RDB 冷备,可以采用下面恢复数据方案:
- 停止 Redis
- 关闭 AOF
- 拷贝 RDB 备份文件
- 重启 Redis
- 确认数据恢复
- 在 redis-cli 开启 AOF(redis config set)
- 此时 AOF 和 RDB 两份数据文件数据同步
- 停止 Redis
- 修改配置文件,开启 AOF
- 重启 Redis
e. 如果当前机器上的所有 RDB 文件全部损坏,那么从远程的云服务上拉取最新的 RDB 快照回来恢复数据。
f. 如果是发现有重大的数据错误,比如某个小时上线的程序一下子将数据全部污染了,数据全错了,那么可以选择某个更早的时间点,对数据进行恢复。