小熙前段时间时间写了Redis的存储机制,接着再说下持久化机制吧,参考了其他大佬的精华和自己的理解。

一. 为什么要持久化

  1. redis是非关系型的内存数据库,数据将被存储在内存中,所以Redis服务器进程退出或者运行Redis服务器的计算机停机,Redis服务器中的数据就会丢失。
  2. 为了避免造成数据丢失,所以数据将被持久化到磁盘上(持久化机制),从而避免了数据的丢失,并且能很快的恢复之前的数据。
    Redis提供了两种持久化机制:
1. AOF持久化
 2. RDB持久化

二. AOF持久化机制

默认情况下AOF机制是关闭的,需要在redis.conf 配置文件中将 appendonly no 调整为 appendonly yes

  1. 流程如图:
  2. 大家可能注意到了,小熙画的AOFl持久化流程图后两步为什么不是一步呢,而是分为了:
第一步:将操作命令追加到 AOF_BUF 缓存区
 第二步:将AOF_buf 缓存区数据同步到 AOF 文件

(1)为什么拆分为两步:

因为 Redis 是单线程响应,如果每次写入 AOF 命令都直接追加到磁盘上的 AOF 文件中,频繁的追加所造成的 IO 开销,那么Redis 的性能就只能取决于你的机器硬件了,为了解决这一问题,提升 Redis 的响应效率所以就添加了一层 aof_buf 缓存层, 所利用的是操作系统的 cache 技术,这样就能提升Redis 的性能了。但是还有一个引申出来的问题,那就是aof_buf 缓存区数据如何同步到 AOF 文件呢?由谁同步呢?

(2)aof_buf 缓存区数据怎么样同步到 aof 文件中:

aof_buf 缓存区数据写入到 aof 文件是由 linux 系统去完成的,由于 Linux 系统调度机制周期比较长,如果系统故障宕机了,意味着一个周期内的数据将全部丢失,这不是我们想要的,所以 Linux 提供了一个 fsync 命令,fsync 是针对单个文件操作(比如这里的 AOF 文件),做强制硬盘同步,fsync 将阻塞直到写入硬盘完成后返回,保证了数据持久化,正是由于有这个命令,所以 redis 提供了配置项让我们自行决定何时进行磁盘同步。

redis 在 redis.conf 配置文件中提供了appendfsync 的三个配置项:
 # appendfsync always
 # appendfsync everysec
 # appendfsync no

 always
 从安全性来说,always是最安全的(丢失数据最少),因为即使出现故障停机,数据库也只会丢失一个事件循环中所产生的命令数据。
 从效率来说,always的效率最慢,因为服务器在每个事件循环都要将AOF缓冲区中的所有内容写入到AOF文件,并且同步AOF文件。
 
 everysec(默认配置)
 从安全性来说,everysec模式下,即使出现故障停机,数据库只会丢失一秒钟的命令数据。
 从效率来说,everysec模式足够快,因为服务器在每个事件循环都要将AOF缓冲区中的所有内容写入到AOF文件,并且每隔一秒就要在子线程中对AOF文件进行同步。
 
 no
 从安全性来说,no模式下,如果出现故障停机,数据库会丢失上次同步AOF文件之后的所有写命令数据,具有不确定性,因为服务器在每个事件循环都要将AOF缓冲区中的所有内容写入到AOF文件,至于何时对AOF文件进行同步,则由操作系统控制。
 从效率来说,no模式和everysec模式的效率差不多。

从以讲述中,会发现一个问题那就是AOF都是追加的,那么肯定会有文件体积过大,运行效率下降,所以Redis引入了重写机制来解决AOF文件过大问题。

  1. AOF的重写:
    AOF文件的重写并不需要对现有的AOF文件进行任何读取、分析或者写入操作,而是通过读取服务器当前的数据库数据来实现的。从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。(小熙这里不过多赘述了,有兴趣可以查看下原理)

三. RDB持久化机制

默认情况下,RDB是开启的,快照方式存储,并且Redis提供了两种持久化方式:手动触发自动触发

  1. 手动触发:
    (1)SAVE命令:会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求,所以线上环境不建议使用
    (2)BGSAVE命令:Redis 主进程会派生出一个子进程,RDB 快照是由子进程来生成的,完成之后,子进程自动结束,服务器进程(父进程)只会在派生子进程的时候短暂的阻塞,这个过程是非常短的,之后服务器进程(父进程)继续处理命令请求,所以推荐使用该命令来手动触发
  2. 自动触发:
    (1)在配置中配置了 save 相关配置信息,比如在配置文件中配置 save 60 15000 ,也可以把它归类为“save m n”格式的配置,表示 m 秒内数据集存在 n 次修改时,会自动触发 bgsave。
    (2)在主从情况下,如果从节点执行全量复制操作,主节点自动执行 bgsave 生成 RDB 文件并发送给从节点
    (3)执行 debug reload 命令重新加载 Redis 时,也会自动触发 save 操作
    (4)默认情况下执行 shutdown 命令时,如果没有开启 AOF 持久化功能则自动执行 bgsave
  3. 优点:
    (1)RDB 快照是某一时刻 Redis 节点内存数据,非常适合做备份,上传到远程服务器或者文件系统中,用于容灾备份
    (2)数据恢复时 RDB 要远远快于 AOF
  4. 缺点:
    (1)RDB 持久化方式数据没办法做到实时持久化/秒级持久化。我们已经知道了 bgsave 命令每次运行都要执行 fork (派生)操作创建子进程,属于重量级操作,频繁执行成本过高。
    (2)RDB 文件使用特定二进制格式保存,Redis 版本演进过程中有多个格式 的 RDB 版本,存在老版本 Redis 服务无法兼容新版 RDB 格式的问题

四. AOF和RDB的区别:

  1. 持久化的方式:
    (1)RDB持久化是通过将某个时间点,Redis服务器存储的数据快照方式,保存到RDB文件中来实现持久化的。
    (2)AOF持久化是通过将Redis服务器执行的所有写命令保存到AOF文件中来实现持久化的。
  2. 安全性:
    (1)AOF持久化的安全性要比RDB持久化的安全性高,即如果发生机器故障,AOF持久化要比RDB持久化丢失的数据要少。
    (2)因为RDB持久化会丢失上次RDB持久化后写入的数据,而AOF持久化最多丢失1s之内写入的数据(使用默认everysec配置的话)。
  3. 文件大小:
    上面已经讲述RDB持久化记录的是结果的快照,而AOF持久化记录的是过程,所以AOF持久化生成的AOF文件会有体积越来越大的问题,所以Redis提供了AOF重写功能来减小AOF文件体积从而提高效率。
  4. 优先级:
    在安全性中的比较可以看AOF是别RDB高的,所以如果Redis服务器开启了AOF持久化功能,Redis服务器在启动时会使用AOF文件来还原数据,如果Redis服务器没有开启AOF持久化功能,Redis服务器在启动时会使用RDB文件来还原数据,所以AOF文件的优先级比RDB文件的优先级高。
    如果AOF和RDB(都存在或者存在其一)都加载失败,那么Redis服务启动会失败,即持久化数据恢复失败。

以上就是小熙的浅谈了,如果感兴趣可以自行搜索相关内容。