• 推荐
  • 评论
  • 收藏

Redis的RDB和AOF持久化机制详解

2021-04-05    2663次浏览

Redis简介

Redis的英文全称为:Remote Dictionary Server(Redis),它是一个 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库。Redis 是一个开源的使用 C语言 编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API(用通俗的语言表示就是:用C语言写的一个程序,这个程序用来存储 key-value类型的数据,它首先将数据放到内存中,然后在持久化写入磁盘指定位置中),Redis 通常被称为数据结构服务器,因为值(value)可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets) 等类型。

Redis持久化

由于Redis的数据都存储在内存中,如果没有配置持久化,redis重启之后数据就会全部丢失,Redis持久化指的是当Redis服务器 崩溃 crash后 或者重启后,用持久化的数据恢复到内存中,以保证应用系统的正确运作。Redis提供了两种用于数据持久化的机制:RDB和AOF;从严格意义上说,Redis服务提供四种持久化存储方案:RDB、AOF、虚拟内存(VM)和DISKSTORE,虚拟内存(VM)方式,从Redis Version 2.4开始就被官方明确表示不再建议使用,Version 3.2版本中更找不到关于虚拟内存(VM)的任何配置范例

RDB(Redis DataBase)机制

RDB在指定的时间间隔,对内存中的数据进行快照存储,具体操作为:将当前内存中数据的快照写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复
  • 在生成数据快照时,将当前进程fork出一个子进程
  • 在子进程中循环所有的数据,将数据以二进制形式写入到临时文件中
  • 当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出

RDB优点

  • 备份方便:采用RDB持久化机制,对于整个Redis数据库来说,将只包含一个文件,这样非常方便进行备份,也很容易的将一个RDB文件移动到其他存储物质上
  • 最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作

RDB缺点

  • 数据易丢失:如果你想在服务器上避免数据的丢失,那么RDB就不适合了,因为RDB文件需要保存整个数据集的状态,因为你可能会在几分钟才保存一次RDB文件,在这种情况下,一旦发生故障停机,你可能会损失好几分钟的数据
  • 多数据处理耗时多:每次在保存RDB的时候,Redis都要fork出一个子进程,并由子进程来进行实际的持久化工作,如果在数据集比较庞大时,fork可能会非常耗时,造成服务器在那么一瞬间会停止处理客户端;虽然AOF重写也需要进行fork,但AOF重写的执行时间间隔有多长,数据的耐久性都不会有任何损失

AOF(Appendonly File)机制

为了弥补RDB的不足(数据的不一致性),所以AOF采用日志的形式(有点像MySql的binlog)来记录每个写操作的指令(将执行过的指令记录下来,数据恢复时按照从前到后的顺序再将指令执行一遍,实现数据恢复),并追加到文件中。
  • AOF的工作原理首先就是将写操作追加到日志文件中
  • 但是文件的冗余内容会越来越多。所以Redis 新增了重写机制。当AOF文件的大小超过所设定的最大值时,Redis就会对AOF文件的内容压缩
  • Redis重启的时候,会根据日志文件的内容将写指令从前到后执行一遍来完成数据的恢复工作。

AOF优点

  • 数据的完整性和一致性更高
  • 记录内容完整,在数据恢复时丢失数据会比RDB少

AOF缺点

  • 因为AOF记录的内容多,文件会越来越大
  • 恢复速度比RDB慢
  • 由于记录频繁,相当耗性能

Redis两种持久化方式总结

  • Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中
  • RDB 持久化适合大规模的数据恢复,但它的数据一致性和完整性较差
  • Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中
  • AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率,在分布式下,可应对大量数据处理问题,但也会存在数据丢失
  • Redis 针对 AOF文件大的问题,提供重写的瘦身机制
  • 若只打算用Redis 做缓存,可以关闭持久化
  • 若打算使用Redis 的持久化,建议RDB和AOF都开启,RDB更适合做数据的备份,AOF适合解决数据的一致性和完整性

知识扩展

AOF优先数据恢复原则

当 Redis 启动时,如果 RDB 持久化和 AOF 持久化都被打开了,那么程序会优先使用 AOF 文件来恢复数据集, 因为 AOF 文件所保存的数据通常是最完整的

RDB文件备份安全

Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制:RDB 文件一旦被创建,就不会进行任何修改。当服务器要创建一个新的 RDB 文件时,它先将文件的内容保存在一个临时文件里面,当临时文件写入完毕时,程序才使用原子地用临时文件替换原来的 RDB 文件。这也就是说,无论何时复制 RDB 文件都是绝对安全的

Redis配置参数:appendfsync

appendfsync:这个参数项是AOF功能最重要的设置项之一,主要用于设置“真正执行”操作命令向AOF文件中同步的策略。在Linux系统中,为了保证操作系统中I/O队列的操作效率,应用程序提交的I/O操作请求一般是被放置在Linux Page Cache中的,然后再由Linux操作系统中的策略自行决定正在写到磁盘上的时机。而Redis中有一个fsync()函数,可以将Page Cache中待写的数据真正写入到物理设备上,而缺点是频繁调用这个fsync()函数干预操作系统的既定策略,可能导致I/O卡顿的现象频繁;使用appendfsync参数可以设置三个同步策略,值分别为 :always、everysec、no,默认的值为everysec
  • always:会使得AOF对数据的保存非常稳健。其设置意义是只要有一个写操作命令执行成功,就执行一次fsync函数调用。所以很显然always的设定值,就是三个选项值中处理效率最慢的
  • no:这个设置值表示Redis不会将执行成功的操作命令真正刷入AOF文件,而是完成操作系统级别的写操作后就认为AOF文件记录成功了,后续的I/O操作完全依赖于操作系统的设定,一般30秒会刷一次
  • everysec:这是默认的设置值,也是可以在数据稳健性和性能上平衡较好策略。它表示每秒钟都做一次fsync函数调用,真正做AOF文件的写入操作