文章目录
1、为什么要持久化?
Redis 是基于内存操作的数据库,所有的数据都保存在内存中,而内存中的数据当程序结束时就会消失,所以我们要想办法把内存中的数据写到磁盘中,当程序正常退出或异常终止时,重新启动就可以从磁盘文件中恢复数据。Redis 有两种持久化机制,分别为 RDB(快照)和 AOF(日志)。
2、RDB(Redis Database)
RDB(Redis Database)持久化策略,就是在符合一定条件下将内存所有的数据持久化到磁盘的 dump.rdb 文件中。RDB 文件是一个经过压缩的二进制文件,有多个部分组成,对于不同类型的键值对,RDB 文件会使用不同的方式来保存它们。RDB 策略是 Redis 默认的持久化策略,也叫快照策略。
为什么叫快照策略?因为持久化到磁盘的数据是某一个时间点内存中所有的数据。
2.1 触发机制
RDB 持久化触发机制分为手动触发和自动触发
- 手动触发
- save 命令:会阻塞当前服务器,直到 RDB 完成为止,在服务器进程阻塞期间,服务器不能处理任何网络请求。如果内存的数据量大的话会造成长时间的阻塞,线上环境一般禁止使用。
- bgsave 命令:(background save),执行 bgsave 命令时 redis 主进程会 fork 一个子进程来完成 RDB 的操作,子进程完成 RDB 任务后向父进程发送信号(操作系统的多进程 Copy On Write 机制,简称 COW)。所以 Redis 主进程阻塞的时间只有 fork 创建子进程那一下,相对于 save,阻塞的时间很短。
https://www.likecs.com/show-205096454.html?sc=400
命令 | save | bgsave |
---|---|---|
IO 类型 | 同步 | 异步 |
是否阻塞 | 是 | 是(阻塞发生在 fork 时,通常非常快) |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外的内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要 fork 子进程,消耗内存 |
- 自动触发
- 配置 redis.conf 文件,根据触发规则自动触发 RDB
# 当在规定的时间内,Redis发生了写操作的个数满足条件,会触发发生BGSAVE命令。
# save <seconds> <changes>
# 当用户设置了多个save的选项配置,只要其中任一条满足,Redis都会触发一次BGSAVE操作
save 900 1 # 900秒之内至少一次写操作
save 300 10 # 300秒之内至少发生10次写操作
save 60 10000 # 60秒之内发生至少10000次写操作
- 执行 shutdown 命令关闭服务器,如果没有开启 AOF 持久化功能,那么会自动执行一次 bgsave
- 执行 flushall 命令
2.2 RDB 执行流程
Redis 使用操作系统的多进程 COW(Copy On Write)机制来实现 RDB 快照持久化
- 执行 bgsave 命令的时候,Redis 主进程会检查是否有子进程在执行 RDB/AOF 持久化任务,如果有的话,服务器拒绝执行此次的 bgsave 命令,直接返回;
- Redis 主进程会 fork 一个子进程来执行执行 RDB 操作,fork 操作会对主进程造成阻塞(影响 Redis 的读写),fork 操作完成后会发消息给主进程,从而不再阻塞主进程。(阻塞仅指主进程 fork 子进程的过程,后续子进程执行操作时不会阻塞);
- RDB 子进程会根据 Redis 主进程的内存生成临时的快照文件,持久化完成后会使用临时快照文件替换掉原来的 RDB 文件。(该过程中主进程的读写不受影响,但 Redis 的写操作不会同步到主进程的主内存中,而是会写到一个临时的内存区域作为一个副本)
- 子进程完成 RDB 持久化后会发消息给主进程,通知 RDB 持久化完成(将上阶段内存副本中的增量写数据同步到主内存)
Redis 的服务器周期性操作函数 serverCron 默认每隔 100 毫秒就会执行一次,该函数用于对正在运行的服务器的各类信息进行维护,它的其中一项工作就是检查 save 选项设置的保存条件是否已经满足,如果满足的话,就执行 BGSAVE 命令。
2.3 优点
- RDB 文件小,非常适合定时备份,用于灾难恢复;
- Redis 加载 RDB 文件的速度比 AOF 快很多,因为 RDB 文件中直接存储的是内存数据,而 AOF 文件中存储的是一条条命令,需要重演命令。
2.4 缺点
- RDB 无法做到实时持久化,若在两次 bgsave 间宕机,则会丢失区间(分钟级)的增量数据,不适用于实时性要求较高的场景;
- RDB 的 cow 机制中,fork 子进程属于重量级操作,频繁操作成本过高;
- 存在老版本的 Redis 不兼容新版本 RDB 格式文件的问题。
3、AOF(Append Only File)
以日志的形式记录每一个写操作,将 Redis 执行过的所有命令都记录下来(读操作不记录)。只许追加文件,但不可以改写文件, Redis 启动之初,会读取该文件,重构数据。也就是说,Redis 启动的时候把日志文件中的所有写操作再执行一遍,来恢复数据。【当两种方式同时开启时,数据恢复 Redis 会优先选择AOF 恢复】
AOF 保存信息的文件的文件名为 appendonly.aof
3.1 开启方式
AOF 默认是关闭的,通过 redis.conf 配置文件进行开启
## 此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能
## 只有在“yes”下,aof重写/文件同步等特性才会生效
appendonly yes
## 指定aof文件名称
appendfilename appendonly.aof
## 指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec
appendfsync everysec
## 在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”
no-appendfsync-on-rewrite no
## aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb”
auto-aof-rewrite-min-size 64mb
## 相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比
## 每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A)
## aof文件增长到A*(1 + p)之后,触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。
auto-aof-rewrite-percentage 100
三种同步策略:
- always:每一条 AOF 记录都立即同步到文件,性能很低,但较为安全。
- everysec:每秒同步一次,性能和安全都比较中庸的方式,也是 Redis 推荐的方式。如果遇到物理服务器故障,可能导致最多 1 秒的 AOF 记录丢失。【推荐】
- no:Redis 永不直接调用文件同步,而是让操作系统来决定何时同步磁盘。性能较好,但很不安全。
3.2 触发机制
和 RDB 类似,AOF 触发机制也分为:手动触发和自动触发
- 手动触发
直接调用 bgrewriteaof 命令
redis-cli -h ip -p port bgrewriteaof
- 自动触发
(aof_current_size > auto-aof-rewrite-min-size ) && (aof_current_size - aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage
#其中aof_current_size和aof_base_size可以在info Persistence统计信息中查看。
3.3 AOF 重写
随着 Redis 的运行,被执行的写命令不断同步到 AOF 文件中,AOF 文件的体积越来越大,极端情况将会占满所有的硬盘空间。如果 AOF 文件体积过大,还原的过程也会相当耗时。为了解决 AOF 文件不断膨胀的问题,需要移除 AOF 文件中的冗余命令来重写 AOF。
AOF Rewrite 虽然是 “压缩” AOF 文件的过程,但并非采用 “基于原 AOF 文件” 来重写或压缩,而是采取了类似 RDB 快照的方式:基于 Copy On Write,全量遍历内存中数据,然后逐个序列化到 AOF 文件中。因此 AOF rewrite 能够正确反应当前内存数据的状态。Redis 提供了 bgrewriteaof 指令用于对 AOF 曰志进行瘦身,其原理就是开辟一个子进程对内存进行遍历,转换成一系列 Redis 的操作指令,序列化到一个新的 AOF 曰志文件中。序列化完毕后再将操作期间发生的增量 AOF 日志追加到这个新的 AOF日志文件中,追加完毕后就立即替代旧的 AOF 曰志文件了,瘦身工作就完成了。
3.4 优点
AOF 只是追加写日志文件,对服务器性能影响较小,速度比 RDB 要快,消耗的内存较少。
3.5 缺点
- AOF 方式生成的日志文件太大,需要不断 AOF 重写,进行瘦身。
- 即使经过 AOF 重写瘦身,由于文件是文本文件,文件体积较大(相比于 RDB 的二进制文件)。
- AOF 重演命令式的恢复数据,速度显然比 RDB 要慢。
X、小结
- RDB 持久化方式能够在指定的时间间隔内对数据进行快照存储;
- AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF 追加保存每次写的操作到文件末尾,Redis 还能对 AOF 文件进行后台重写,使得 AOF 文件的体积不至于过大。
- 只做缓存,如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化
- 同时开启两种持久化方式,在这种情况下,当 Redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整。RDB 的数据不实时,同时使用两者时服务器重启也只会找 AOF 文件。