Redis持久化
2021-08-23 17:52:21 0 举报
AI智能生成
Redis持久化
作者其他创作
大纲/内容
Redis持久化
简介
Redis是内存数据库,宕机后数据会消失
Redis重启后快速恢复数据,要提供持久化机制
Redis有两种持久化方式:RDB和AOF
Redis持久化不保证数据的完整性
当Redis用作DB时,DB数据要完整,所以一定要有一个完整的数据源(文件/MySQL),在系统启动时,从这个完整的数据源中将数据load到Redis
RDB
Redis默认的存储方式,通过快照(snapshotting)完成
触发快照方式
1. 符合自定义配置的快照规则
2. 执行save或bgsave命令
3. 指定flushall命令
4. 执行主从复制操作(第一次)
配置参数定期执行快照
redis.conf
save 900 1
900秒内至少1个键被更改则进行快照
执行流程
1.Redis父进程首先判断:当前是否在执行save/bgsave/bgrewriteaof的子进程,如果在执行则直接返回
2.父进程调用fork(调用OS函数复制主进程)创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令
3.父进程fork后,不再阻塞父进程,可以响应其他命令
4.子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换
5.子进程发送信号给父进程表示完成,父进程更新统计信息
文件结构
1. 头部5字节固定为”REDIS“
2. 4字节”RDB“版本号,当前为9,填充后为0009
3. 辅助字段,以key-value形式
4. 存储数据库号码
5. 字典大小
6. 过期key
7. 主要数据,以key-value形式存储
8. 结束标志
9. 校验和checksum
优点
RDB是二进制压缩文件,占用空间小,便于传输
主进程fork子进程,可以最大化Redis性能,主进程不能太大,复制过程中主进程阻塞
缺点
不保证数据完整性,会丢失最后一次快照以后更改的所有数据
AOF
Redis另一种持久化方式,默认不开启
开启AOF后,Redis将所有对数据进行过写入的命令(及其参数)记录到AOF文件,以此达到记录数据库状态的目的
当Redis重启后只要按照顺序回放命令即可恢复到原始状态
配置
redis.conf
appendonly yes
dir ./
appendfilename appendonly.aof
原理
AOF文件中存储的是redis命令,同步命令到AOF文件分为三阶段
阶段
命令传播
Redis将执行完的命令、参数、参数个数等信息发送到AOF程序中
当一个Redis客户端需要执行命令时,它通过网络连接,将协议文本发送给Redis服务器
服务器在接到客户端的请求之后,会根据协议文本内容,选择适当的命令函数,并将各个参数从字符串文本转换为Redis字符串对象
每当命令函数执行成功之后,命令参数都会被传播到AOF程序
缓存追加
AOF程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的AOF缓存中
当命令被传博到AOF程序之后,程序会根据命令及参数,将命令从字符串对象转换回原来的协议文本
协议文本生成后,会被追加到redis.h/redisServer结构的aof_buf结尾
redisServer结构维持着Redis服务器的状态,aof_buf域则保存着所有等待写入到AOF文件的协议文本
文件写入和保存
AOF缓存中的内容被写入到AOF文件末尾,如果设定的AOF保存条件被满足,fsync()或fdatasync()会被调用,将写入的内容真正保存到磁盘中
每当服务器常规任务函数被执行或事件处理器被执行时,aof.c/flushAppendOnlyFile函数都会被调用,这个函数执行两个工作
WRITE
根据条件,将aof_buf中的缓存写入到AOF文件
SAVE
根据条件,调用fsync或fdatasync函数,将AOF文件保存到磁盘中
保存模式
AOF_FSYNC_NO
不保存
这种模式下,每次调用flushAppendOnlyFile(),WRITE都会被执行,SAVE会被略过
本模式下,SAVE只会在以下情况执行
Redis被关闭
AOF功能被关闭
系统写缓存被刷新(可能是缓存已被写满,或定期保存操作被执行)
本模式下SAVE操作都会引起Redis主进程阻塞
AOF_FSYNC_EVERYSEC
每秒保存一次,默认
这种模式中,SAVE原则上每秒执行一次,因为SAVE是由后台子进程调用的,所以不会引起服务器主进程阻塞
AOF_FSYNC_ALWAYS
每个命令保存一次,不推荐
本模式下,每次执行完一个命令之后,WRITE和SAVE都会被执行
因为SAVE是由Redis主进程执行的,所以SAVE执行期间会阻塞主进程
AOF重写
Redis可以在AOF体积变得过大时,自动地在后台对AOF进行重写
重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合
实际上,AOF重写并不需要对原有的AOF文件进行任何写入和读取,它针对的是数据库中键的当前值
Redis不希望AOF重写造成服务器无法处理请求,所以Redis将AOF重写程序放到子进程里执行,这样处理的最大好处
1. 子进程进行AOF重写期间,主进程可以继续处理命令请求
2. 子进程带有主进程的数据副本,可以避免锁,且保证数据的安全性
子进程在进行AOF重写期间,主进程还需要继续处理命令,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致
为了解决这个问题,Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用,Redis之进程在接到新的写命令之后,除了会将这个写命令的协议内容追加到现有的AOF文件之外,还会追击到这个缓存中
触发方式
1. 配置触发
redis.conf
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
2. 执行bgrewriteaof命令
AOF文件载入与数据还原
因为AOF文件包含了重建数据库状态所需的所有命令,所以服务器只要读入并重新执行一遍AOF里的写命令,就可以还原服务器关闭之前的数据库状态
步骤
1. 创建一个不带网络连接的伪客户端
因为Redis的命令只能在客户端上下文中执行,而载入AOF时所用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的客户端来执行AOF的写命令
伪客户端执行命令的效果和带网络连接的客户端执行命令效果完全一样
2. 从AOF文件中分析并读取一条写命令
3. 使用伪客户端执行被读出的写命令
4. 重复2,3,直到AOF文件中所有写命令都被处理完毕
混合持久化
RDB和AOF各有优缺点,Redis4.0开始支持两者的混合持久化
如果开启混合持久化,aofrewrite时就直接把rdb的内容写到aof文件开头
加载时,首先会识别AOF文件是否以REDIS字符串开头,如果是就按RDB格式加载,加载完RDB后继续按AOF格式加载剩余部分
开启
aof-use-rdb-preamble yes
对比
1. RDB存数据快照,采用二进制压缩存储,AOF存操作命令,采用文本存储
2. RDB性能高,AOF性能较低
3. RDB在配置触发状态会丢失最后一次快照以后更改的数据,AOF设置为每秒保存,最多丢失2秒数据
4. 主从模式下
Redis以主服务器模式运行,RDB不会保存过期键值对数据
Redis以从服务器模式运行,RDB会保存过期键值对,当主服务器向从服务器同步时,再清空过期键值对
5. AOF写入文件时,对过期key会追加一条del命令,执行AOF重写时,会忽略过期key和del命令
应用场景
内存数据库
rdb + aof, 数据不容易丢失
缓存服务器
rdb,性能高
不建议只使用aof,性能差
0 条评论
下一页