redis 持久化
为什么需要持久化,持久化是什么
redis 是基于内存的所以速度快,没有与磁盘交互。但是缺点就是断电或宕机数据就没了,这是不可接受的。持久化就是把内存的数据也存在磁盘上,用于 redis 重启后时恢复数据。两种方式 RDB 和 AOF
RDB
快照操作,持久化当前内存中的数据。分为手动触发和自动触发
手动触发
save 命令:同步方式,在持久化未完成前阻塞 redis 主进程(不用想了,直接 pass,相当于某个时间段内 redis 不可用了)
bgsave 命令:异步方式,执行 fork 操作开启一个子进程来持久化,这样就能一边继续提供服务(主进程),一边做持久化(子进程)。也会阻塞 redis,只不过时间非常短,只是 fork 的操作过程阻塞,fork 完成意味着子线程已经创建好了,就不会阻塞了
持久化过程
- 执行命令
- 如果是 save ,阻塞 redis 主进程
- 如果是 basave,阻塞 redis 主进程,fork 一个子进程,子进程创建成功后释放 redis 主进程
- 当前内存所有数据写入 rdb 文件(注意是替换文件,每次手动持久化后产生的 rdb 内容都是不一样的,持久化完成后替换文件)
- 持久化完成,通知 redis 主进程,做一些统计信息;如果是 save 命令触发的,释放 redis 主进程
自动触发
配置文件配好了规则自动触发 bgsave 来异步持久化,规则配置如下:
# 如果900秒内有1条Key信息发生变化,则进行快照
save 900 1
# 如果300秒内有10条Key信息发生变化,则进行快照
save 300 10
# 如果60秒内有10000条Key信息发生变化,则进行快照
save 60 10000
# 关闭RDB快照功能,redis 只作为缓存,不需要持久化功能时
save ""
其他相关配置:
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入(如果关闭持久化功能,这里要改为 no,不然会报错,亲身经历)
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
优缺点
-
优点
- RDB 文件是某个时间节点的快照,默认使用 LZF 算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景
- Redis 加载 RDB 文件恢复数据要远远快于 AOF 方式
-
缺点
- RDB 方式实时性不够,无法做到秒级的持久化(频繁fork一个子进程性能消耗时比较大的)
- 可能丢失最后一次持久化数据(持久化过程宕机)
- RDB 文件是二进制的,没有可读性
- 版本兼容RDB文件问题
AOF
针对 RDB 快照的缺点产生了 AOF,AOF 是追加 redis 命令的形势来持久化的。在 redis 修改数据后,写入 aof 日志文件(写后日志),像 mysql 是先写日志,再修改数据(写前日志)
写后日志的好处是会避免额外的开销,比如语法检查等;缺点就是写时宕机会数据丢失,命令比较多时会比较多的写入文件,压力会比较大
实现原理
- 命令追加,当服务器执行完一个命令时,先把这个命令写入到一个 buffer 缓冲区
- fork 一个子进程把缓冲区的命令追加写入 aof 文件,什么时候把缓冲区内容写入 aof ?有下面 3 中策略
Always
,同步写回:每个写命令执行完,立马同步地将日志写回磁盘Everysec
,每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘No
,操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
配置
# appendonly参数开启AOF持久化,默认是关闭的
appendonly no
# AOF持久化的文件名,默认是appendonly.aof
appendfilename "appendonly.aof"
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的
dir ./
# 同步策略
# appendfsync always
appendfsync everysec
# appendfsync no
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof出错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
混合方式
Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。
两种方式的结合,原理还是上面说的,问题是两个持久化文件 (rdb 文件和 aof 文件),redis 启动时使用哪个呢?(两个文件的最终数据肯定是一样的)