Redis的持久化是什么

Redis 的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是 Redis 的持久化机制。

Redis 的持久化机制有三种

  • AOF日志:每执行一条写操作指令,就把该指令记录到一个文件中
  • RDB快照:将某一时刻的内存数据,以二进制方式写入磁盘
  • 混合持久化方式:Redis4.0新增,集成了AOF和RDB的优点

AOF日志如何实现

AOF日志是持续增量的备份,是基于写命令存储的可读的文本文件。AOF日志会在持续运行中持续增大,由于Redis重启过程需要优先加载AOF日志进行指令重放以恢复数据,恢复时间会无比漫长。所以需要定期进行AOF重写,对AOF日志进行瘦身。目前AOF是Redis持久化的主流方式。

AOF默认是关闭的,通过redis.conf配置文件进行开启

优点:

  • AOF只是追加写日志文件,对服务器性能影响较小,速度比RDB要快,消耗的内存较少

缺点:

  • AOF方式生成的日志文件太大,需要不断AOF重写,进行瘦身。
  • 即使经过AOF重写瘦身,由于文件是文本文件,文件体积较大(相比于RDB的二进制文件)。
  • AOF重演命令式的恢复数据,速度显然比RDB要慢。

RDB快照如何实现的

RDB快照是某个时间点的一次全量数据备份,是二进制文件,在存储上非常紧凑。

RDB执行流程

Redis 使用操作系统的多进程 cow(Copy On Write) 机制来实现RDB快照持久化

  1. 执行bgsave命令的时候,Redis主进程会检查是否有子进程在执行RDB/AOF持久化任务,如果有的话,直接返回
  2. Redis主进程会fork一个子进程来执行执行RDB操作,fork操作会对主进程造成阻塞(影响Redis的读写),fork操作完成后会发消息给主进程,从而不再阻塞主进程。(阻塞仅指主进程fork子进程的过程,后续子进程执行操作时不会阻塞)
  3. RDB子进程会根据Redis主进程的内存生成临时的快照文件,持久化完成后会使用临时快照文件替换掉原来的RDB文件。(该过程中主进程的读写不受影响,但Redis的写操作不会同步到主进程的主内存中,而是会写到一个临时的内存区域作为一个副本)
  4. 子进程完成RDB持久化后会发消息给主进程,通知RDB持久化完成(将上阶段内存副本中的增量写数据同步到主内存)

优点

  • RDB文件小,非常适合定时备份,用于灾难恢复
  • Redis加载RDB文件的速度比AOF快很多,因为RDB文件中直接存储的时内存数据,而AOF文件中存储的是一条条命令,需要重演命令。

缺点

  • RDB无法做到实时持久化,若在两次bgsave间宕机,则会丢失区间(分钟级)的增量数据,不适用于实时性要求较高的场景
  • RDB的cow机制中,fork子进程属于重量级操作,并且会阻塞redis主进程
  • 存在老版本的Redis不兼容新版本RDB格式文件的问题

Redis 4.0 混合持久化

仅使用RDB快照方式恢复数据,由于快照时间粒度较大,时回丢失大量数据。

仅使用AOF重放方式恢复数据,日志性能相对 rdb 来说要慢。在 Redis 实例很大的情况下,启动需要花费很长的时间。

Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。相当于:

  • 大量数据使用粗粒度(时间上)的rdb快照方式,性能高,恢复时间快。
  • 增量数据使用细粒度(时间上)的AOF日志方式,尽量保证数据的不丢失。

在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

三种持久化方式没有更好,酌情使用即可