07.Redis持久化
# 01.Redis持久化
# 0、概述
# 1、持久化说明
- 使用缓存的时候,我们经常需要对内存中的数据进行持久化也就是将内存中的数据写入到硬盘中
- 大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了做数据同步
Redis 不同于 Memcached 的很重要一点就是,Redis 支持持久化,而且支持 3 种持久化方式
- 快照(snapshotting,RDB)
- 只追加文件(append-only file, AOF)
- RDB 和 AOF 的混合持久化(Redis 4.0 新增)
# 2、CPA原理
1、CPA原理是分布式存储理论的基石:C(一致性);A(可用性);P(分区容忍性);
2、当主从网络无法连通时,修改操作无法同步到节点,所以“一致性”无法满足
3、除非我们牺牲“可用性”,也就是暂停分布式节点服务,不再提供修改数据功能,直到网络恢复
一句话概括CAP: 当网络分区发生时,一致性和可用性两难全
# 3、Redis主从同步策略
1、主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。
2、当然,如果有需要,slave 在任何时候都可以发起全量同步。
3、Redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
注意点
如果多个Slave断线了,需要重启的时候,因为只要Slave启动,就会发送sync请求和主机全量同步
当多个同时出现的时候,可能会导致Master IO剧增宕机
# 1、全量同步: RDB
Redis 提供了两个命令来生成 RDB 快照文件:
save
: 同步保存操作,会阻塞 Redis 主线程bgsave
: fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项
注:
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份
1)从服务器连接主服务器,发送SYNC命令;
2)
主服务器
接收到SYNC命令
后,开始执行BGSAVE命令生成RDB文件
并使用缓冲区记录此后执行的所有写命令;3)主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
4)
从服务器
收到快照文件后丢弃所有旧数据
,载入收到的快照
;5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
7)
完成上面几个步骤后就完成了从服务器数据初始化的所有操作,从服务器此时可以接收来自用户的读请求。
优点
RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,体积小,适用于备份、全量复制等场景
Redis加载RDB文件恢复数据要远远快于AOF方式
缺点
RDB方式实时性不够,
无法做到秒级的持久化
每次调用bgsave都需要fork子进程,fork子进程属于重量级操作,
频繁执行成本较高
RDB文件是二进制的,
没有可读性
(AOF文件可以手动修改或者补全)版本兼容RDB文件问题
# 2、增量同步:AOF
# 1、AOF概述
- 增量复制的过程主要是
主服务器
每执行一个写命令
就会向从服务器发送相同的写命令
- 从服务器接收并执行收到的写命令
- 而AOF日志采用写后日志,即先写内存,后写日志
# 2、AOF工作流程
AOF日志记录Redis的每个写命令分为以下五个步骤
1)命令追加(append)
- 服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器的 aof_buf 缓冲区
2)文件写入(write)
将 AOF 缓冲区的数据写入到 AOF 文件中
- 这一步需要调用
write
函数(系统调用),write
将数据写入到了系统内核缓冲区之后直接返回了(延迟写) - 注意此时并没有同步到磁盘
- 这一步需要调用
关于何时将 aof_buf 缓冲区的内容写入AOF文件中,Redis提供了三种写回策略
1、
Always
,同步写回每个写命令执行完
,立马同步地将日志写回磁盘
2、
Everysec
,每秒写回- 每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区
- 每隔一秒把缓冲区中的内容写入磁盘
3、
No
,操作系统控制的写回- 每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区
- 由操作系统决定何时将缓冲区内容写回磁盘
3)文件同步(fsync)
- AOF 缓冲区根据对应的持久化方式(
fsync
策略)向硬盘做同步操作 - 这一步需要调用
fsync
函数(系统调用),fsync
针对单个文件操作,对其进行强制硬盘同步 fsync
将阻塞直到写入磁盘完成后返回,保证了数据持久化
- AOF 缓冲区根据对应的持久化方式(
4)文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的
5)重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复
write
:
- 写入系统内核缓冲区之后直接返回(仅仅是写到缓冲区),不会立即同步到硬盘(有丢数据风险)
- 同步硬盘操作通常依赖于系统调度机制,Linux 内核通常为 30s 同步一次
fsync
:
fsync
用于强制刷新系统内核缓冲区(同步到到磁盘),确保写磁盘操作结束才会返回
# 3、AOF 重写
当 AOF 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件
这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小
AOF 文件重写期间,Redis 还会维护一个
AOF 重写缓冲区
该缓冲区会在
子进程创建新 AOF 文件期间
,记录服务器执行的所有写命令
当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾
使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致
最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作
# 4、AOF校验机制
- AOF 校验机制是 Redis 在启动时对 AOF 文件进行检查,以判断文件是否完整,是否有损坏或者丢失的数据
- 这个机制的原理其实非常简单,就是通过使用一种叫做
校验和(checksum)
的数字来验证 AOF 文件 - 这个校验和是通过对整个 AOF 文件内容进行 CRC64 算法计算得出的数字
- 如果文件内容发生了变化,那么校验和也会随之改变
- 因此,Redis 在启动时会
比较计算出的校验
和与文件末尾保存的校验和
(计算的时候会把最后一行保存校验和的内容给忽略点) - 从而判断 AOF 文件是否完整,如果发现文件有问题,Redis 就会拒绝启动并提供相应的错误信息
- AOF 校验机制十分简单有效,可以提高 Redis 数据的可靠性
注:类似地,RDB 文件也有类似的校验机制来保证 RDB 文件的正确性,这里就不重复进行介绍了
# 3、RDB&AOF混合4.0版
- Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法
- 简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作
注:默认关闭,可以通过配置项
aof-use-rdb-preamble
开启
- 如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头
- 这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响
- 而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了
- 因此,就不会出现文件过大的情况了,也可以避免重写开销
缺点:AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差
# 4、RDB&AOF比较
1)RDB 优点
- RDB 二进制文件很小,AOF文件为命令数据很大
- RDB恢复文件直接还原数据(很快),SOF 需要一次执行命令(很慢)
2)AOF 优点
- RDB 无法实时持久化,可能丢失数据,AOF如果是 everysec,最多丢失 1 秒的数据
- 生成 RDB 文件的过程是比较繁重,虽然 BGSAVE 子进程不会阻塞主线程,但是会消耗大量资源
- 在 Redis 版本演进中有多个版本的 RDB,有版本兼容问题
- AOF 具有可读性,可以修改AOF 文件恢复数据
总结
Redis 保存的数据丢失一些也没什么影响的话,可以选择使用 RDB
不建议单独使用 AOF,因为时不时地创建一个 RDB 快照可以进行数据库备份、更快的重启以及解决 AOF 引擎错误
如果保存的数据要求安全性比较高的话,建议同时开启 RDB 和 AOF 持久化或者开启 RDB 和 AOF 混合持久化