Redis 持久化

持久化:

RDB 和 AOF 两种持久化机制,持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前的持久化的文件即可实现数据恢复。

1.RDB

RDB 是把当前进程数据生成快照保存到硬盘的过程,触发 RDB 持久化过程分为自动和手动的
触发机制:
save : 阻塞当前服务器,直到RDB 过程完成。对于内存比较大的实例会造成长时间阻塞。save已废弃
bgsave: redis 进程执行fork 操作创建子进程,RDB 持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork 阶段,一般时间很短。
显然bgsave 命令是针对save 阻塞问题做到优化。因此Redis 内部所有的涉及RDB 的操作都采用bgsave 的方式

自动触发RDB 的持久化机制:
1 )使用 save 相关配置,如 save m n 命令。 表示 m 秒内数据集存在n次修改时,自动触发 bgsave
2)如果从节点执行全量复制操作,主节点自动执行bgsave 生成RDB 文件并发送给从节点
3 ) 执行debug reload 命令重新加载Redis时,也会自动触发save
4 ) 执行 shutdown命令时,如果没有开启AOF 持久化功能则自动执行bgsave

RDB 过程

1 执行bgsave 命令,Redis 父进程判断当前是否存在正在执行的子进程,如RDB/ AOF 子进程,如果存在 bgsave 命令直接返回
2 父进程执行 fork 操作创建子进程,fork 操作过程中父进程会阻塞,通过info stats 命令查看latest_fork_usec 选项,可以获取一个 fork操作的耗时
3 fork 完成之后,bgsave 不再阻塞父进程。
4 子进程创建RDB 文件, 根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换
5 进程发生信号给父进程表示完成,父进程更新统计信息

RDB 文件的处理

保存:
RDB 文件保存在 dir 配置指定的目录下, 文件名通过dbfileName 配置指定
动态执行: config set dir {name}
该命令可以在磁盘写满的时候,遇到 下次 RDB/AOF 操作的时候,就会动态更改路径
压缩:
Redis 默认采用LZF 算法对生成的RDB 文件做压缩处理。默认开启
 动态修改是否开启:config set rdbcompression {yes|no}
压缩会消耗CPU ,但是可大幅降低文件体积,方便传输

RDB 优缺点

优点: 紧凑压缩的二进制文件,代表某个时间点上的数据快照适用于备份和全量复制。
RDB 恢复数据远远快于 AOF 的方式
缺点:
没办法实时持久化,因为每次都要 fork 子进程。属于重量级操作
RDB 是特定二进制格式保存,并且新老版本无法兼容这种格式。

2.AOF

AOF 持久化: 以独立日志的方式记录每次写命令,重启时再重新执行AOFS文件中的命令达到恢复数据的目的。 主要是为了解决数据持久化的实时性,目前是主流方式。
开启AOF 功能需要设置配置: appendonly yes
工作流程:
命令写入 (append) 文件同步 (sync) 重写(rewrite) 重启加载(load)
1.所有写入命令 追加到 aof_buf 缓冲区
2. AOF 缓冲区根据对应的策略向硬盘做同步操作
3. 随着AOF 文件越来越大,需要定期对AOF 文件进行重写
4. 当redis 服务器重启时,可以加载AOF 文件进行数据恢复

命令写入:

AOF  命令写入内容直接是文本协议格式。
why?
1 文本协议具有很好的兼容性
2 开启AOF 后,所有写入命令都包含追加操作,直接采用协议格式,避免二次处理
3 文本协议具有可读性,方便直接修改和处理
为什么把命令追加到aof_buf ?
单线程下的Redis,如果AOF 都直接追加到硬盘,那么性能完全取决当前硬盘负载。先写入buf中,可以提供多种缓冲区同步硬盘的策略,在性能和安全性之间平衡。

文件同步

提供多种AOF 缓冲区同步文件策略
三种配置:  always everysec no
配置为 always , 每次写入都同步 AOF文件,一般redis 只支持大约几百 TPS 写入。不建议配置
配置为 no 由于操作系统同步AOF 文件的周期不可控,而且会加大每次同步硬盘的数据量,数据安全性无法保证
配置为everysec 是建议的策略。只有在系统突然宕机的情况下丢失1秒的数据.

重写机制

随着命令不断写入AOF ,文件会越来越大,为了解决这问题,Redis 引入 AOF 重写机制压缩文件体积。
AOF 文件重写是把redis进程内的数据转化为写命令同步到新的AOF 文件的过程
为什么重写会变小?
1) 进程内已经超时的数据不再写入文件
2) 旧的AOF 文件含有无效命令。如, del .hdel , srem...  。重写使用进程内数据 直接生成,这样新的AOF 文件只保留最终数据的写入命令
重写过程的手动触发和自动触发
手动: 直接调用 bgrewriteaof命令
自动:根据
auto-aof-rewrite-min-size  的参数触发。 表示 运行AOF 重写时文件的最小体积
auto-aof-rewrite-percentage:  代表当前AOF 文件空间(aof-current-size)和上一次重写后AOF文件空间(aof-base-size)的比值

问题定位与优化

question : 如何改善fork 操作的耗时
answer:
优先使用 物理机或高效支持fork操作的虚拟化技术
控制redis实例 最大可用内存。fork耗时和内存成正比
合理配置Linux内存分配策略,避免物理内存不足导致fork失败。
避免不必要的全量复制或降低fork操作频率,如放宽AOF 自动触发时机

多实例部署

Redis 单线程架构使得无法充分利用 CPU 多核特性,通常的做法是再一台计算机上部署多个Redis 实例。
当多个实例开启AOF 重写后,彼此之间会产生CPU 和IO 资料竞争。

采取: 子进程工作进行隔离
info Persistence 为我们提供监控子进程运行状况的度量指标
属性名 属性值
rdb_bgsave_in_progress bgsave 子进程是否再运行
rdb_current_bgsave_time_sec 当前运行bgsave的时间 -1表示未运行
aof_enabled 是否开启AOF 功能
aof_rewrite_in_progress AOF 重写子进程是否在运行
aof_rewrite_scheduled 在bgsave 结束后是否运行AOF 重写
aof_current_rewrite_time_sec 当前运行AOF 重写的时间 -1表未运行
aof_current_size AOF文件当前的字节数
aof_base_size AOF 上次重写的字节数

基于以上的指标,可以通过外部程序轮询控制AOF 重写操作的执行


流程图.png
流程介绍:
1) 外部程序定时轮询监控机器上所有Redis 实例
2) 对于开启AOF 的实例,查看 currentsize-basesize / basesize 确认增长率
3) 增长率超过特定阈值时,执行bgrewriteraof 命令触发当前实例AOF 重写
4)运行期间循环检查指标,直到AOF 重写结束
5) 确认实例AOF 重写完成后,再检查其他实例并重复 2-4步。保证机器内每个Redis实例AOF 重写串行化执行。

\color{#228B22}{学习小总结,不对之处,欢迎大神们喷我。可以的话顺手点个赞吧~~!}
\color{red}{警: 禁止抄袭,转载说明出处 }

你可能感兴趣的:(Redis 持久化)