文章目录
  1. 1. Redis持久化
    1. 1.1. RDB持久化方案
      1. 1.1.1. RDB的缺点
    2. 1.2. AOF持久化方案
      1. 1.2.1. AOF缺点
      2. 1.2.2. AOF重写
      3. 1.2.3. AOF重写流程,主线程,子线程的工作:
    3. 1.3. AOF重写过程,图表式:

Redis持久化

RDB持久化方案

在Redis运行时,RDB程序将当前内存中的数据库快照保存到磁盘中,当Redis需要重启时,RDB程序会通过重载RDB文件来还原数据库。
RDB主要包括两个功能:

  • 保存(rdSave)
    rdSave负责将内存中的数据库数据以RDB格式保存到磁盘中,如果RDB文件已经存在将会替换已有的RDB文件。保存RDB文件期间会阻塞主进程,这段时间期间将不能处理新的客户端请求,直到保存完成为止。
    为避免主进程阻塞,Redis提供了rdbSaveBackground函数。
    在新建的子进程中调用rdSave,保存完成后会向主进程发送信号,同时进程可以继续处理新的客户端请求。
  • 读取(rdbLoad)
    当Redis启动时,会根据配置的持久化模式,决定是否读取RDB文件,并将其中的对象保存到内存中。载入RDB过程中,
    每载入1000个键就处理一次已经等待处理的客户端请求,但是目前仅处理订阅功能的命令,其他一律返回错误信息,因为发布订阅功能是不写入数据库的,也就不保存Redis数据库的
RDB的缺点

要理解RDB的缺点,需要了解RDB有保存点的概念。在默认的redis.conf中可以看到如下的默认配置:

1
2
3
save 900 1 #如果15分钟内,有1个键被修改
save 300 10 #如果6分钟内,有10个键被修改
save 60 10000 #如果60秒内有10000个键被修改

上面表示只要满足任意一个条件时,将会进行快照保存。为了保证IO读写性能不会成为Redis的瓶颈,一般都会创建一个比较大的值作为保存点,会出现如下缺点:

  • 此时如果保存点设置过大,就会导致宕机丢失的数据过多。保存点设置过小,又会造成IO瓶颈
  • 当对数据进行保存时,可能会由于数据集过大导致操作耗时,这会导致Redis可能在短时间内无法处理客户端请求。

AOF持久化方案

以协议文本的方式,将所有对数据库进行写入命令记录到AOF文件,达到记录数据库状态的目的。

AOF功能:

  • 保存
    1.将客户端请求的命令转换成网络协议格式
    2.将协议内容字符串追加到变量server.aof_buf中
    3.当AOF系统达到设定的条件时,会调用aof_fsync(文件描述符)将数据写入磁盘
  • 读取
    1.创建模拟的客户端
    2.读取AOF保存的文本,还原数据为原命令和原参数。然后使用模拟的客户端发出这个命令请求
    3.继续执行第二步,直到读取完AOF文件

AOF系统设定条件:

  • 在前面提到的AOF系统到达设定条件时,将会调用aof_fsync(文件描述符)将数据写入磁盘,这是AOF性能的关键点。目前Redis支持三种保存条件机制:
    1.AOF_FSYNC_NO:不保存
    此模式下,每执行一条客户端命令,都会将协议字符串追加到server.aof_buf中,但是不会执行写入磁盘。写入磁盘只发生在:redis被正常关闭、AOF功能关闭、系统写缓存已满或后台定时保存操作被执行,此三种情况都会阻塞主进程,导致客户端请求失败。
    2.AOF_FSYNC_EVERYSECS:每一秒保存一次
    由后台子进程调用写入保存,不会阻塞主进程。如果发生宕机,那么最大丢失数据会在2s以内的数据。这也是默认的设置选项
    3.AOF_FSYNC_ALWAYS:每执行一个命令都保存一次
    这种模式下,可以保证每一条客户端指令都被保存,保证数据不会丢失。但缺点是性能大大下降,因为每一次操作都是都独占性的,需要阻塞主进程
AOF缺点
  • AOF文件通常会大于等于相同数据集的RDB文件
  • AOF模式下性能与RDB模式性能高低,主要取决于AOF选用的fsync模式
AOF重写

AOF需要将所有的命令都保存到磁盘,那么这个文件会随着时间变得越来越大,读取也会变得很慢。
Redis提供了AOF重写机制,帮助减少文件的大小,具体实现如下:

1
LPUSH list 1 2 3 4 5

1
LPOP list
1
LPOP list
1
LPUSH list 1

最初保存到AOF文件的将会是四条指令。但是经过AOF重写后,会变成一条指令:

1
LPUSH 1 3 4 5

AOF重写流程,主线程,子线程的工作:
  • 主线程创建子线程,执行AOF文件重写
  • 将子线程在执行写操作过程中的执行命令追加到AOF缓冲区和AOF重写缓冲区
  • 当子线程完成AOF重写工作后,它会向主线程发送一个信号,主线程接收到该信号,会调用一个信号处理函数,并执行下面工作
  • 将AOF重写缓冲区中的所有内容写入到新AOF文件中,这时新AOF文件所保存的数据库状态将和服务器当前的数据库状态一致
  • 将新的AOF文件进行改名,原子地覆盖现有的AOF文件,完成新旧两个AOF文件的替换
  • 这个信号处理函数执行完毕后,父进程可以继续接受请求命令

AOF重写过程,图表式:

时间 服务器进程(主进程) 子进程
T1 执行命令 set k1 v1
T2 执行命令set k1 v2
T3 执行命令set k1 v3
T4 创建子进程,执行AOF文件重写 开始AOF文件重写
T5 执行命令set k2 10086 执行重写操作
T6 执行命令set k3 12345 执行重写操作
T7 执行命令set k4 23423 完成AOF文件重写,向父进程发送信号
T8 接收到子进程发来的信号,将命令set k2 10086、set k3 12345、set k4 22222追加到新AOF文件的末尾
T9 用新的AOF文件覆盖旧AOF文件

Redis Server端持久化部分操作图解
Redis Server端持久化部分操作图解

文章目录
  1. 1. Redis持久化
    1. 1.1. RDB持久化方案
      1. 1.1.1. RDB的缺点
    2. 1.2. AOF持久化方案
      1. 1.2.1. AOF缺点
      2. 1.2.2. AOF重写
      3. 1.2.3. AOF重写流程,主线程,子线程的工作:
    3. 1.3. AOF重写过程,图表式: