一,Redis持久化
Redis持久化即将内存中的数据持久化到磁盘中,在下一次重启后还能进行使用,Redis持久化分为RDB和AOF两种,我们接下来分别介绍RDB和AOF的内部原理和区别
RDB
Redis运行时会将当前的内存快照存入至磁盘中,Redis重新启动后会将快照以二进制的形式给加载进入内存中,其中rdbSave
和rdbLoad
函数至关重要
什么时候会触发RDB?
- Redis停机时会触发
- 使用命令
save m n
- 主从同步执行全量复制
- debug reload命令重新加载Redis
保存
在RDB文件期间,主进程会被阻塞,直至保存完成,其中也分为了两种不同的保存方式SAVE
和BGSAVE
:
def SAVE():
rdbSave()
def BGSAVE():
pid = fork()
if pid == 0:
# 子进程保存 RDB
rdbSave()
elif pid > 0:
handle_request()
else:
# pid ==-1
# 处理 fork 错误
handle_fork_error()
- SAVE: 该方法会阻塞Redis主进程,此时不会响应用户请求,直至保存完成位置
- **BGSAVE:**该方法不会阻塞Redis主进程,主线程会查看是否已经fork了一个子线程,如果fork则返回,否则fork一个子进程采用
CopyOnWrite
机制将当前的快照存入磁盘中
SAVE,BGSAVE,BGREWRITEAOF能同时执行吗?
对于SAVE来说:
由于SAVE是阻塞当前主进程的,所以此时此刻不管是用户命令还是
BGSAVE
和BGREWRITEAOF
都无法执行,在执行SAVE
指令前会检查BGSAVE
是否在执行,如果在执行则不能进行SAVE
对于BGSAVE来说:
**BGSAVE与BGSAVE:**通过上述代码我们可以知道,当BGSAVE正在执行时,会检查子进程是否fork如果fork了子进程则直接返回,所以是不能同时执行的
**BGSAVE与BGREWRITEAOF:**BGSAVE正在执行时,BGREWRITEAOF会延迟收到指令直至BGSAVE执行完毕。如果BGREWRITEAOF正在执行,BGSAVE会直接返回报错,无法同时执行。
载入
Redis服务器启动时,就会进行rdbLoad函数,此时在载入期间每载入1000条数据就会处理一次当前的用户命令,当然这里的用户命令只能时订阅与发布功能相关的,其他的命令都会统一拒绝。
在载入的时候会优先选择AOF,如果没有设置AOF才会使用RDB
RDB文件结构
一个RDB的文件结构如下所示:
- **REDIS:**该字符标识着RDB文件的开始,相当于魔数
- RDB-VERSION(四字节): 记录了当前文件RDB的版本号,读取的时候要使用对于版本号的方法读取
- DB-DATA: 该部分会在RDB文件中出现多次,保存着一个服务器上非空数据库的所有数据
- SELECT-DB: 代表着该键值对所属的数据库号码,读入RDB文件时,会根据该号码不断切换数据库
- KEY-VALUE-PAIRS: 代表着一个键值对的数据,每个键值对的数据会用以下结构来进行保存
OPTIONAL-EXPIR