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

RDB(快照)

RDB持久化是把当前进程数据生成快照保存当硬盘的过程,分为手动触发和自动触发

手动触发机制

手动触发分别对应save(废弃,不推荐)和bgsave(推荐)

save(阻塞,不推荐)

save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存比较大的实例会造成长时间阻塞,线上环境不建议使用

bgsave(优化阻塞,推荐)

bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一半时间很短
image.png

自动触发机制

  • save m n:m秒内数据集存在n次修改时,自动触发bgsave
  • 执行debug reload 命令重新加载Redis时会触发save操作
  • 默认执行shutdown时,如果没有开启AOF持久化功能,则自动执行bgsave

bgsave流程说明

image.png

  • bgsave是主流的持久化方式流程说明如下:
    1.执行bgsave命令,Redis父进程判断是否存在正在执行的子进程,入RDB/AOF,如果存在则直接返回
    2.不存咋则父进程执行fork操作创建子进程,此时会阻塞,通过info stats可查看最近一个fork操作,单位为us
    image.png
    3.父进程fork完成后,返回Background saving started信息后不再阻塞父进程,可以继续相应其他命令
    4.子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换,lastsave可以获取最后一次生成RDB的时间
    image.png
    5.进程发送信号给父进程表示完成,父进程更新统计信息。可以使用info persistence命令查看详情
    image.png

RDB文件的处理

保存:RDB保存在dir配置指定的目录下,配置文件默认为redis的配置文件
image.png
image.png

  • 可以通过执行config set dir ,config set dbfilename 运行期间动态执行,下次运行时RDB文件会保存在新目录。
    当遇到坏盘或者磁盘写满时,可以通过config set dir在线修改文件路径

压缩

Redis默认采用LZF算法对生成的RDB文件做压缩处理,压缩后的文件大小远远小于内存大小,默认开启

校验

如果Redis加载损坏的RDB文件时拒绝启动,可以使用Redis提供的redis-check-dump检测RDB文件

RDB的优缺点

  • 优点:
    1.RDB是一个紧凑压缩的二进制文件,非常适用于备份,全量复制等场景
    2.RDB恢复数据远远快于AOF的方式

  • 缺点:
    1.RDB方式要执行fork操作创建子进程,属于重量级操作,频繁执行成本比较高
    2.老版本Redis服务无法兼容新版RDB格式

AOF(日志,主流方式,默认不开启)

AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。解决了数据持久化的实时性,已经是Redis持久化的主流方式

使用AOF

AOF默认不开启,其配置开启和保存文件名如下
image.png
保存路径同RDB一直,通过dir指定

AOF流程

命令写入(append)、文件同步(sync)、文件重写(rewirte)、重启加载(load)
image.png

  • 流程
    1.所有的写入命令会追加到aof_buf(缓冲区)中
    2.AOF缓冲区根据对应的策略向硬盘做同步操作
    3.随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的
    4.当Redis服务器重启时,可以加载AOF文件进行数据恢复

命令写入

AOF写入文件的内容直接是文本协议格式。

  • AOF采用文本协议格式好处
    1.文本协议具有很好的兼容性
    2.开启AOF后,直接采用协议格式,避免二次处理开销
    3.文本协议具有客户端,方便修改和处理

  • AOF吧命令追加到aof_buf中好处
    1.Redis使用单线程响应命令,如果直接写硬盘,那么性能完全取决于硬盘负责性能
    2.可以通过多种缓冲区同步硬盘的策略,在性能和安全性方面做出平衡

文件同步

Redis提供多种AOF缓冲策略,配置文件如下,提供3中策略,默认为everysec
image.png

no: don't fsync, just let the OS flush the data when it wants. Faster.

always: fsync after every write to the append only log. Slow, Safest.

everysec: fsync only one time every second. Compromise.

  • 3种策略如下:
    1.no:同步硬盘操作由操作系统负责,通常同步周期最长30秒,数据安全性无法保证
    2.always:每次下入同步AOF文件,一般SATA硬盘,只能支持大约几百TPS写入,硬盘为Redis性能瓶颈,不建议使用
    3.everysec:默认配置,fsync同步操作由专门线程每秒调用一次,兼顾性能和数据安全性。在系统突然宕机的情况下丢失1秒的数据

重写机制

随着不断地写入AOF,文件会越来越大,Redis引入AOF重写机制压缩文件体积。
Redis进程内的数据转化为写命令同步到新AOF文件的过程

  • AOF文件变小的原因:
    1.进程内已超时的数据不在写入文件
    2.旧的AOF文件还有无效命令(del、hdel、srem等)
    3.多条写命令可以合并为一个

AOF重写触发机制

  • 手动触发:直接调用bgrewriteaof命令
  • 自动触发:根据auto-aof-rewrite-percentage和auto-aof-rewrite-min-size参数
    1.auto-aof-rewrite-percentage:当前AOF文件空间和上一次重写后AOF空间的比值,默认为100
    2.auto-aof-rewrite-min-size:代表运行AOF重写时文件最小体积,默认为64MB
    image.png
    触发时机参数比较复杂,不细说O(∩_∩)O

重启加载(AOF、RDB)

AOF和RDB文件都可用于服务器重启时的数据恢复
image.png
流程说明如上图Redis启动时优先加载AOF

问题与优化

Redis持久化功能一直是影响Redis性能的高发地

fork操作

fork是个重量级操作,回赋值父进程的空间内存页表

  • 改善操作
    1.优先使用物理机或者高效支持fork操作的虚拟化技术,避免使用Xen
    2.控制Redis实例最大可用内存,建议Redis实例内存控制在10GB内
    3.合理配置Linux内存分配策略,避免物理内存不足导致fork失败
    4.降低fork操作频率,适度放宽AOF自动触发时机,避免不必要的全量复制等

子进程开销监控和优化

子进程负责AOF或者RDB文件的重写,主要设计CPU、内存、硬盘三部分

AOF追加阻塞

开启AOF持久化时且策略使用everysec时,Redis使用另一条线程每秒执行fsync同步硬盘。当系统资源繁忙时会造成Redis主线程阻塞

多实例部署

Redis单线程架构导致无法充分利用CPU多核特性,通常做法是在一台机器上部署多个Redis实例。当多个实例开启AOF重写后,彼此之间会产生对COU和I/O的竞争,需要采取措施把子进程工作进行隔离


这个家伙很懒,啥也没有留下😋