📖 Redis 持久化
📑 单机 Redis 的问题
数据丢失问题
Redis是内存存储,服务器重启可能会导致数据丢失
实现 Redis 数据持久化
并发能力问题
搭建主从集群,实现读写分离
故障恢复问题
如果 Redis 宕机,则服务不可用,需要一种自动的故障恢复手段
利用 Redis 哨兵,实现健康监测和自动恢复
存储能力问题
搭建分片集群,利用插槽机制实现动态扩容
📑 RDB 持久化
Redis Database Backup file
1️⃣ RDB全称Redis Database Backup file (Redis数据备份文件),也被叫做Redis数据快照。
2️⃣ 简单来说就是把内存中的所有数据都记录到磁盘中。
3️⃣ 当redis实例故障重启后,从磁盘读取快照文件,恢复数据.
4️⃣ 快照文件称之为 RDB 文件,默认是保存在当前运行目录
[root@localhost ~]# redis-cli
127.0.0.1:6379> save # 由 Redis 主线程来运行 RDB ,会阻塞所有命令
ok
127.0.0.1:6379> bgsave # 开启子进程执行 RDB , 避免主进程受到影响
Background saving started
📚 Redis 停机时 会执行一次 RDB
save
# 由 Redis 主线程来运行 RDB ,会阻塞所有命令bgsave
# 开启子进程执行 RDB , 避免主进程受到影响
Saving the final RDB snapshot before exiting
Redis 内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:
# 900 秒内,如果至少有 1 个 key 被修改,则执行 bgsave, 如果 save "" 称之为禁用 RDB
save 900 1
save 300 10
save 60 10000
RDB 的其它配置也可以在 redis.conf 文件中设置:
# 是否压缩 , 建议不开启, 压缩也会销毁 cpu ,磁盘的话不值钱
rdbcompression yes
# RDB 文件名称
dbfilename dump.rdb
# 文件保存的路径目录
dir ./
📚 RDB 的 fork 原理
bgsave 开始时会 fork 主进程得到子进程,子进程共享主进程的内存数据。完成 fork 后读取内存数据并且写入 RDB 文件
Redis 生成 RDB 文件时的 写时复制技术
Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,可以正常处理写操作。
bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。 bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。
- 如果主线程对这些数据也都是读操作(例如图中的键值对 A),那么主线程和 bgsave 子进程相互不影响。
- 如果主线程要修改一块数据(例如图中的键值对 C), 那么这块数据就会被复制一份,生成该数据的副本。然后 bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。
📚 小结
1️⃣ RDB 方式 的 bgsave 基本流程是什么?
- 当我们 Redis 主线程 启动
bgsave
命令时,首先会去判断是否有对应的子线程已经在 bgsave 了,如果没有则此时会 fork 出一条对应的子线程共享同一个内存数据空间。 - 当创建完成子线程时,此时子线程会异步去读取 共享内存中的数据写入到一个新的 RDB 文件当中,这里需要注意的是 此时 主线程还是可以进行读写操作的,主要是写操作 会触发一个操作系统内的 复制时写(copy on write) 操作 —— 这个操作呢 主要就是
2️⃣ RDB 会在什么时候执行?save 60 1000 代表什么含义?
- 默认是服务停止时
- 代表的是在60s 内至少 1000 次 修改则触发 RDB
3️⃣ RDB 的缺点?
- RDB 执行间隔时间长,两次RDB 之间写入数据有丢失的风险
- fork 子进程、压缩、写出 RDB 文件都比较耗时
📑 AOF 持久化
Append Only File(追加文件)
AOP 全程为 Append Only File (追加文件),Redis 处理的每一个写命令都会记录在 AOF 文件,可以看做是命令日志文件。(有点类似 MySQL 的 binLog)
AOF 默认是 关闭的 ,需要修改 redis.conf 配置文件来开启 AOF:
# 是否开启 AOF 功能 ,默认为 no
appendonly yes
# AOF 文件的名称
appendfilename "appendonly.aof"
AOF 的命令记录的频率也可以通过 redis.conf 文件来配置
# 表示每执行一次写命令 , 立即记录到 AOF 文件
appendfsync always
# 写命令执行完先放入到 AOF 缓冲区,然后表示每隔 1 秒将缓冲区数据写入到 AOF 文件,是默认方案
appendfsync everysec
# 写命令执行完先放入 AOF 缓冲区,由操作系统决定何时 将缓冲区 内容写回磁盘
appendfsync no
解决 AOF 重复字段占用空间的问题
因为是记录命令,AOF 文件会比 RDB 文件大的多。而且 AOF 会记录对同一个 key 的多次写操作,但只有最后一次写操作才有意义。通过执行 bgrewriteaof
命令,可以让 AOF 文件执行重写功能,用最少命令达到相同的效果。
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started # 异步执行
Redis 也会在触发阈值时自动去重写 AOF 文件。阈值也可以在 redis.conf 中配置:
# AOF 文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF 文件体积最小多大以上 才会触发重写
auto-aof-rewrite-min-size 64mb
AOF 的工作流程
1️⃣ 命令追加(append):所有写命令都会被追加到AOF缓存区(aof_buf)中。
2️⃣ 文件同步(sync):根据不同策略将AOF缓存区同步到AOF文件中。
3️⃣ 文件重写(rewrite):定期对AOF文件进行重写,以达到压缩的目的。
4️⃣ 数据加载(load):当需要恢复数据时,重新执行AOF文件中的命令。
⭐ AOF 与 RDB 的对比
RDB 与 AOF 各有各自的优缺点,如果是对数据安全性要求较高,则实际开发中往往会采用结合的方式
RDB | AOF | |
---|---|---|
持久化方式 | 定时对整个内存做快照处理 | 记录每一次执行的命令 |
数据完整性 | 不完整,会丢失两次备份之间的数据 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,相对较小 | 记录命令,文件体积较大 |
宕机恢复速度 | 很快 | 慢 |
数据恢复优先级 | 低,因为数据完整性不如 AOF | 高,因为数据完整性较高 |
系统资源占用 | 高,大量 CPU 和 内存消耗 | 低,主要是磁盘IO资源,但是AOF重写时会占用大量 CPU 和内存资源 |
使用场景 | 可以容忍分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高常见 |