Redis持久化机制

1、Redis数据持久化的必要性

由于redis是基于内存的数据库,面临数据掉电易失的风险,要避免数据丢失,最好将内存数据持久化到磁盘等永久存储介质上。服务重启时,会先加载磁盘文件内的数据到内存,完成数据恢复。

2、RDB(RedisDB)

对内存中的redis全量数据进行时点快照并序列化,以文件形式保存到磁盘上,生成的是dump.rdb二进制文件。到了dump时间点就生成一份新的rdb文件,同时覆盖掉旧的。服务重启时直接将dump文件反序列化并加载到内存中,数据恢复速度较快,也是redis默认的持久化方式。hdfs的nameNode也是用类似的方式生成fsimage文件来做持久化的,hdfs的nameNode也是用类似的方式生成fsimage文件来做持久化的

执行方式:

阻塞式:

类似JVM的stop-the-world,做快照的时候不能处理客户端请求,客户端可以使用save命令触发。优点原理简单,能保证数据一致性,缺点是对用户不友好。

非阻塞式:

服务端做数据快照的时候,可以继续处理客户端的请求,客户端可以使用bgsave命令触发。优点是对客户端友好,但复杂度高,必须解决做快照的同时,并发写操作造成的数据不一致问题。
redis中的所有key和value是分为两个部分单独存储的,两个数据区之间建立映射关系,数据修改只是映射关系的改变。
大体机制:当服务端接收到bgsave命令后,服务端不会立马执行快照操作,而是选择合适的时机fork一个子进程,这个子进程全量继承父进程的key数据集和映射关系。实现类cow的效果,子进程只保证dump时点当前的数据一致性,至于并发修改的数据就交给下一次dump来持久化。

配置策略:

可以通过客户端发命令的方式,也可以写在配置文件中实现自动持久化。
save 900 1 //如果在900秒内发生了超过1次k-v更新就触发一次dump
save 300 10 //如果在300秒内发生了超过10次k-v更新就触发一次dump
save 60 10000 //如果在60秒内发生了超过1万次k-v更新就触发一次dump
dbfilename dump.rdb //快照文件名
dir /opt/redis/rep //快照存储路径
【每完成一次快照后,时间计和更新计数器都会清零】

优点:

  1. 全量备份,可以做到针对不同时间点的多版本恢复(此时需要避免覆盖问题,推荐用多服务器来存储dump文件)。
  2. 备份文件紧凑单一,利于网络传输,适合灾难恢复。
  3. 恢复大数据集速度比AOF快。

缺点:

  1. 最后一次快照时如果掉电,并发写的数据将丢失,所以适合存储能容忍这种风险的场合。
  2. fork过程会造成毫秒级的耗时,会造成短暂的拒绝相应。

3、AOF(AppendOnlyFile)

实时记录每一条写数据的命令,形成binlog,服务重启时会原样执行一遍aof文件中的所有命令,达到数据恢复的目的,但恢复速度比rdb式慢。hdfs中提供了类似的方式,edit-log,只是默认时关闭的。

几乎可以做到不丢失任何数据,也可以控制丢失一秒内的数据。
备份的数据量太大,不够紧凑,io交互频繁。
写入机制:在现代操作系统中,程序执行write系统调用时,是先将数据写到一个内存buffer中,等到buffer满或者用户执行fsync或fdatasync
指令时才会将buffer数据刷到disc上,所以未刷盘的数据存在掉电丢失风险。

落盘策略由appendfssync选项控制:

  • always:服务端每接收一个更新指令都刷到磁盘,不会发生数据丢失,但是io太过频繁效率很低。
  • everysecond:每隔1秒钟刷一次盘,有可能丢失一秒钟的数据,效率适中。
  • no:服务端不主动刷盘,数据何时落盘完全取决于操作系统,只有当buffer满了才会刷盘,丢失数据量不确定,效率最高。

AOF重写机制:

由于AOF文件时间长了会很大,可以通过分析文件内容,将多条命令合并为一条,将对同一个key的多次操作只保留最新的那一次。

AOF重写过程

  • fork一个子进程负责重写AOF文件
  • 子进程创建一个临时文件来写入AOF数据
  • 父进程开辟一个内存缓冲区接收新的写命令
  • 子进程重写完毕后,父进程会获得一个信号,父进程将新收到的写命令通过子进程写入临时文件
  • 用临时文件替换掉旧的AOF文件

AOF重写的触发

  1. 手动式:通过客户端发送bgrewriteaof命令。
  2. 自动式:必须在配置文件中配置如下两个参数
    • auto-aof-rewrite-min-size 500mb //只有当aof文件大于等于500M时,服务器才会重写aof文件,避免过小文件的重写问题。
    • auto-aof-rewrite-min-percentage 60 //在满足最小阈值的前提下,超过上一次重写后生成的文件体积的60%时将触发重写,避免了无限循环重写。(如果尚未做过重写,就以启动时的AOF文件体积作为对比基准,如果此值为0,则表示关闭自动重写功能)。

优点:

  • 默认每秒刷盘,性能好不阻塞服务,最多丢失一秒数据。
  • 如果发生误操作(flushall等),只要文件未被重写,立即停止服务将,AOF文件最后的flushall命令删除,然后重启redis服务实现数据恢复。

缺点:

  • 相同数据集,AOF比RDB大很多。
  • 数据恢复速度比RDB慢。