Redis 持久化

Redis 存储数据时,对于同一份数据,分别在内存和硬盘上都进行了存储,当查询某个数据时,直接从内存中读取,硬盘的数据用来在 Redis 重启时恢复内存中的数据,Redis 提供了两种内存持久化的策略

1. RDB 持久化策略

定期备份,会在指定的时间间隔内,将内存中的数据集快照写入磁盘,

1.1. 手动触发

"定期"可以手动触发,通过 Redis 客户端,执行save命令或者bgsave命令来触发快照生成,不过执行save命令时,Redis 会集中处理快照,就会阻塞其它命令,而bgsave就不会影响Redis 服务器处理其它请求和命令,此时采用的是一种"多进程"的方式来完成的

  1. 首先,执行bgsave命令之后,Redis 父进程会判断当前进程是否存在其他正在执行的子进程,如 RDB/AOF 子进程,如果存在就直接返回,不存在的话就执行fork创建子进程,fork 过程中父进程会阻塞
  2. 当父进程 fork 完成后,不再阻塞父进程,可以执行其他命令
  3. 子进程创建 RDB 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换
  4. 进程发送信号给父进程表示完成,父进程更新统计信息

由于 fork 采用的是"写时拷贝"的策略,所以在进行 bgsave 的过程中,绝大部分数据时不需要改变的,整体来说拷贝过程也挺快

而 Redis 生成的 RDB 文件是存放在 Redis 的工作目录中的,也可以在配置文件中找到该路径

切换到该目录之后就能找到 rdb 文件了

执行 RDB 镜像操作时,会把生成的快照数据先保存在一个临时文件中,当这个快照生成完毕之后,再把原来的 rdb 文件删除,然后更新临时文件的名称为 dump.rdb,如果是save命令就直接在当前进程中往同一个文件中写入数据了

需要注意的是 dump.rdb 文件不能随便修改,可能会使 Redis 无法正常启动

通过执行 redis-check-rdb dump.rdb可以检查格式是否有误

通过手动输入命令bgsave的方式来生成快照:

1.2. 自动触发

除了手动,也可以自动触发,通过 shutdown 命令关闭 Redis 服务器时会触发自动生成快照,进行主从复制的时候,主节点也会自动生成 rdb 快照,然后把 rdb 快照内容传输给从节点,所以说,在正常关闭 Redis 服务器时会触发生成 rdb,如果是异常重启,例如 kill -9 或者服务器掉电这样的情况就不会触发,也就会丢失当前没有存储快照的数据

此外,在 Redis 的配置文件中也可以配置一些 Redis 自动触发快照的条件:

这里表示需要满足过 900 秒,并且修改 1 次才会自动触发,如果设置为 save ""表示取消自动触发

如果修改配置文件之后,重启客户端配置才会生效

2. AOF 持久化策略

由于 RDB 采用的是定时备份的策略,所以两次快照之间的数据就可能会丢失,而 AOF 采用的是实时备份的策略。

修改配置文件中的 appendonly 为 yes 就能够开启 AOF

之后每次进行的操作都会被记录到 appendonly.aof 文本文件中,当 redis 服务器异常关闭,再次启动时也能通过读取 appendonly.aof 文件进行恢复

2.1. 写入流程

采用 AOF 之后,redis 既需要写硬盘,有需要写内存,但也并不会对性能有过大的影响,AOF 采用的是先把数据写入内存缓冲区,积累到一定数量时再统一写入硬盘,也就大大减少了写入硬盘的次数

但是,当面的策略也存在一个问题,当数据在缓冲区中没来的及写入内存时,Redis 服务器出现问题了,那么次数缓冲区的数据就丢失了,所以控制缓冲区的刷新频率就很有必要了,Redis 中提供了三种不同的刷新缓冲区策略:

|--------------------------|-------------------------------|----------------------|
| 策略 | 含义 | 特点 |
| appendfsync always | 每次执行写命令后都立即将 AOF 缓冲区中的内容刷新到磁盘 | 数据安全性最高,Redis 性能最低 |
| appendfsync everysec | 每秒将 AOF 缓冲区中的内容刷新到磁盘一次 | 在性能和数据安全性之间做了一个较好的平衡 |
| appendfsync no | 由操作系统决定何时将 AOF 缓冲区中的内容刷新到磁盘 | 数据安全性最低 |

2.2. 重写机制

由于 aof 文件是记录每一次的操作的,所以会持续增长,增长到一定大小就会影响 Redis 下一次启动的时间,对于一些操作的记录其实也可以进行合并,所以存在很多不必要的记录

重写的时候就是把当前内存中的数据获取出来,以 AOF 的格式写入到一个新的 AOF 文件中,也就是记录一次结果状态,也就类似于 RDB 生成的快照,只不过 RDB 那里是按照二进制来生成的,AOF 重写是按照文本格式来生成的

在重写的时,还是会 fork 一个新的进程,父进程还继续接收客户端新的请求,继续把这些请求产生的 AOF 数据先写入到缓冲区,再刷新到原有的 AOF 文件里,只不过父进程又准备了一个 aof_rewrite_buf 缓冲区,专门用来存放 fork 之后接收到的数据,子进程把 AOF 数据写完之后,父进程再把 aof_rewrite_buf 缓冲区中的内容也写入到新的 AOF 文件中,然后替换到原来的 AOF 文件

如果在执行bgrewriteaof时,发现 Redis 正在进行 AOF 重写,就会直接返回,如果 Redis 正在生成 rdb 文件的快照,AOF 重写操作就会阻塞,快照生成完毕再执行重写

3. 混合持久化

在配置文件中 aof-use-rdb-preamble yes表示开启混合持久化

执行bgrewriteaof之后再来看 appendonly.aof 文件,发现存储的结果变味了和 rdb 文件一样的二进制

是因为此时采用了"混合持久化"的方式,也就是按照 aof 的方式,把每一个操作都记录到文件中,在触发 aof 重写时,就会把当前的内存状态按照 rdb 的二进制格式写入到新的 aof 文件中,之后再存储就还是原来的 aof 文本格式

相关推荐
m0_748239338 分钟前
【MySQL】深度学习数据库开发技术:使用CC++语言访问数据库
数据库·mysql·数据库开发
S-X-S16 分钟前
Java面试题-Redis缓存
java·redis·缓存
A__tao1 小时前
在线SQL转xorm struct-GO在线工具集
数据库·sql·golang
天才奇男子1 小时前
数据库约束(2)
android·数据库·mysql·adb
追寻落在生命里的那道光1 小时前
Oracle数据连接 Dblink
数据库·oracle
XiaoLeisj2 小时前
【MySQL — 数据库基础】深入解析MySQL的聚合查询
数据库·mysql
小姚要加油!2 小时前
数据库创库建表处理
大数据·数据库
卓怡学长2 小时前
w200基于spring boot的个人博客系统的设计与实现
java·数据库·spring boot·后端·spring·intellij-idea
*老工具人了*2 小时前
管理etcd的存储空间配额
数据库·chrome·etcd
饮长安千年月2 小时前
CVE-2024-13025-Codezips 大学管理系统 faculty.php sql 注入分析及拓展
开发语言·数据库·sql·网络安全·php