Redis的持久化

Redis的持久化

由于 Redis 是一个内存数据库,所谓内存数据库,就是将数据库中的内容保存在内存中,这与传统的MySQL,Oracle等关系型数据库直接将内容保存到硬盘中相比,内存数据库的读写效率比传统数据库要快的多(内存的读写效率远远大于硬盘的读写效率)。但是保存在内存中也随之带来了一个缺点,一旦断电或者宕机,那么内存数据库中的数据将会全部丢失。

Redis 支持两种形式的持久化:

  • RDB(snapshotting)持久化
  • AOF(append-only-file)持久化

RDB持久化

RDB文件是一个经过压缩的二进制文件,由多个部分组成。

触发方式

RDB 有两种触发方式,分别是自动触发手动触发

  • 自动触发。在redis.conf配置文件中的 SNAPSHOTTING下有一行是save m n,这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘,表示m秒内数据集存在n次修改时,自动触发bgsave。
  • 手动触发。就是手动输入持久化指令,包括save 和bgsave

持久化方式:分为两种,一种是save(阻塞式),另一种是bgsave(非阻塞式)

  • save:该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。
  • bgsave:执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
    • 在bgsave期间,服务器会拒绝save、bgsave等指令,这是为了避免父进程(服务器进程)和子进程同时执行两个rdbSave调用,防止产生竞争条件。

    • bgsave的实现方式:

    1. 设置一个saveparams数组,数组中保存的元素是一个saveparam结构,该结构表示一个save自动触动条件。Redis允许有多个触发条件,因此该数组可能有多个元素;
    2. 每个saveparam结构包含两个属性,seconds和changes分别对应触发条件的多少秒内存在多少次修改;
    3. Redis还维护着一个dirty计数器和一个lastsave属性,前者表示在上次RDB持久化之后进行了多少次修改,后者是一个UNIX时间戳,表示上次修改时间;
    4. Redis会周期性的根据dirty计数器和lastsave属性对saveparams数组进行检查,如果满足就执行持久化。

RDB持久化的优缺点分析

优势:

  • RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。
  • 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作
  • RDB在恢复大数据集时的速度比 AOF 的恢复速度要快

劣势:

  • RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作(内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑),频繁执行成本过高(影响性能)。
  • RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题(版本不兼容)。
  • 在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失)。

AOF持久化

与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存redis服务器所执行的写命令来记录数据库状态的。

AOF文件中的所有命令都以redis命令请求协议的格式保存。命令请求会先保存到AOF缓冲区里面,之后再定期写入并同步到AOF文件中。

AOF 持久化功能的实现可以分为命令追加(append)文件写入、**文件同步(sync)**三个步骤。

  • 命令追加:当 AOF 持久化功能处于打开状态时,服务器在执行完一个写命令之后, 会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾。
  • 文件写入:Redis 的服务器进程就是一个事件循环(loop), 这个循环中的文件事件负责接收客户端的命令请求, 以及向客户端发送命令回复, 而时间事件则负责执行像serverCron 函数这样需要定时运行的函数。因为服务器在处理文件事件时可能会执行写命令, 使得一些内容被追加到 aof_buf 缓冲区里面, 所以在服务器每次结束一个事件循环之前, 它都会调用flushAppendOnlyFile 函数, 考虑是否需要将 aof_buf 缓冲区中的内容写入和保存到 AOF 文件里面;
  • 文件同步:根据配置不同,Redis的同步策略也是不一样的,分为三种:
    1. always:将缓冲区的所有内容全部写入并同步到硬盘上的AOF文件中;
    2. everysec:将缓冲区的所有内容全部写入到AOF,如果距离上次同步超过一秒钟,则执行同步;
    3. no:将缓冲区内容全部写入到AOF文件中,但是不进行同步,何时同步由系统决定。

在现代操作系统中,硬盘文件的write功能不是直接进行的,一般是先存放在内存的写缓冲区,等到缓冲区被填满或者超过时间阈值,再真正的将数据写入到磁盘上,因此对于磁盘上的文件来说,写入和同步是两种行为。

AOF重写

  • 类似于MySQL的重做日志,随着时间的流逝,磁盘上的AOF文件会越来越大,不加以控制的话会对服务器产生影响,并且AOF文件越大,进行数据恢复还原所需要的时间也就越长,因此Redis提供重写功能;
  • AOF的重写不会对现有AOF文件做任何修改操作,该功能的实现是通过分析服务器当前的数据库状态实现的;
  • 比如一个集合包含6个元素,Redis的AOF文件会写入rpush list “A”、“B”、“C”、“D”、“E”、“F”指令;
  • 由于Redis的单线程特性,分析服务器当前数据状态执行AOF重写会阻塞服务器一段时间,因此AOF重写是通过生成子进程并且提供AOF缓冲区来保证重写期间的并发修改;
  • 完成重写后,新文件会以原子操作的形式覆盖旧AOF文件。

AOF持久化的优缺点分析

优势:

  • AOF可以更好的保护数据不丢失。
    一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据,Redis进程挂了,最多丢掉1秒钟的数据;
  • AOF日志文件以append-only模式写入,写入性能比较高。
    AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修;
  • AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
    因为在rewrite log的时候,会对其中的指令进行压缩,创建出一份需要恢复数据的最小日志出来。再创建新日志文件的时候,老的日志文件还是照常写入。当新的merge后的日志文件ready的时候,再交换新老日志文件即可。
  • 适合做灾难性的误删除紧急恢复。
    AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据。

劣势:

  • 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大,恢复速度慢。
    我们可以简单的认为AOF就是日志文件,此文件只会记录“变更操作”(例如:set/del等),如果server中持续的大量变更操作,将会导致AOF文件非常的庞大,意味着server失效后,数据恢复的过程将会很长;事实上,一条数据经过多次变更,将会产生多条AOF记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为AOF持久化模式还伴生了“AOF rewrite”。

  • AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的。如果你要保证一条数据都不丢,也是可以的,AOF的fsync设置成没写入一条数据,fsync一次,那就完蛋了,Redis的QPS大降。

  • AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。
    所以说,类似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。

参考文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值