跳至主要內容

Redis的持久化RDB和AOF

pptg大约 5 分钟

1. 简介

Redis是基于内存的数据库, 一旦发生发生宕机所有的数据就都会丢失,此时如果从数据库再次同步数据会影响数据库的性能。因此Redis提供了自身的持久化方法

目前有四种持久化方案: RDB、AOF、虚拟内存(VM)和DISKSTORE,但后两者并不被建议使用, 所以主流的方案只剩下了RDB和AOF

2. RDB(Redis DataBase)

RDB持久化将当前进程的数据保存到磁盘上,快照的值可能早于当前的值, 可以手动或自动触发

2.1 触发方式

2.1.1 手动触发

  • save: 阻塞当前Redis服务器,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用
  • bgsave命令: Redis进程执行fork操作创建子进程,RDB持久化过程由子 进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短
bgsave
bgsave

bgsave流程如下:

  • redis客户端执行bgsave命令或者自动触发bgsave命令
  • 主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回
  • 如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作
  • 子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件
  • 同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)

注意

bgsave不阻塞主进程,也不能频繁执行,这样会导致频繁的全量写入磁盘和频繁的fork子进程,影响性能。

这个时候就需要增量同步了

2.1.2 自动触发

自动触发的四种条件:

  • redis.conf中配置save m n,即在m秒内有n次修改时,自动触发bgsave生成rdb文件
  • 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点
  • 执行debug reload命令重新加载redis时也会触发bgsave操作
  • 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作

2.2 RDB的优缺点

  • 优点
    • RDB使用LZF压缩算法, 压缩后的提及远小于原内存大小
    • RDB加载恢复的速度远快于AOF方法
  • 缺点
    • 实时性不强,不能频繁同步

2.3 深入理解

1. RDB如何保证同步期间的数据一致性

在RDB同步的时候(bgsave)会fork一个进程数据,但是在存储的过程中,主进程的数据仍有可能被修改,如果发生修改则将未修改的数据单独复制一份,RDB继续读取这个副本即可

数据一致性
数据一致性

2. 快照期间Redis崩溃怎么办

当次快照不生效,使用最后一次成功的快照恢复Redis数据

3. AOF(Append Only File)

不同于MySQL等日志,Redis考虑到高性能的需求,其AOF采用的是写后日志,即先写入数据再记录日志,这样做的好处有:

  • 避免语法检查: 因为写成功了,所以不需要再次检查
  • 不阻塞写操作: 先写后记

但也存在着缺点:

  • 在写后和记前,如果发生了宕机,则会发生数据丢失
  • 主线程写入磁盘,导致写盘慢、阻塞后续操作
  • 触发AOF重写时,需要fork主进程,导致短暂阻塞

2.1 实现方式

  • 命令追加:命令追加到服务器的aof_buf缓冲区
  • 文件写入和同步: AOF提供三种策略来决定何时将缓存区的命令写入磁盘
    • Always: 每次命令执行完就写入
    • Everysec: 每秒写入一次
    • No: 操作系统决定何时写入

2.2 AOF重写

1. AOF文件重写

AOF记录着每次的命令,但有些命令是冗余的, 比如连续两条set key aset key b显然可以合并成set key b,Redis通过文件重写机制来对AOF文件进行精简

2. AOF重写时机

提供了两种重写的时机:

  • auto-aof-rewrite-min-size: 表示运行AOF重写时文件的最小大小,默认为64MB
  • auto-aof-rewrite-percentage: (当前AOF大小 - 上次重写后AOF大小)/上次重写后AOF大小, 达到这个值就重写

3. 重写期间Redis崩溃怎么办

当次重写失效,依旧使用旧日志

4. 重写过程

  • 主线程fork出子进程重写AOF日志
  • 此时有新的数据写入,主线程将命令记录到两个AOF日志缓冲区(此时如果时always写回则直接写入到日志文件,否则等重写完成后追加到新的日志文件中)
  • 子线程重写日志完成后,主线程追加AOF日志缓冲
  • 替换原日志文件
AOF重写
AOF重写

3. 数据恢复

数据恢复只需重启Redis即可:

  • Redis重启后首先检查是否存在AOF,Redis会优先加载AOF
  • 如果AOF不存在则会检查是否存在RDB,并加载
  • 如果RDB不存在则正常启动

4. RDB+AOF混合方式

Redis 4.0中提出了一种混合方法

  • RDB以一定的频率执行,成功后清空AOF日志
  • 在两次RDB之间用AOF记录期间操作

这样就可以即享受RDB的速度优势,又可以享受AOF的实时性优势了