Redis两种持久化策略分析
Redis专题地址:https://www.cnblogs.com/hello-shf/category/1615909.html
SpringBoot读源码系列:https://www.cnblogs.com/hello-shf/category/1456313.html
Elasticsearch系列:https://www.cnblogs.com/hello-shf/category/1550315.html
数据结构系列:https://www.cnblogs.com/hello-shf/category/1519192.html
一、为什么要持久化
redis为什么这么受欢迎的一个主要原因就是QPS高,也就是快。为什么快?主要原因数据都在内存里。如果redis服务器宕机了,内存中的数据是不是都丢了呢?是的,所以我们需要持久化,防止redis宕机导致的缓存数据丢失。有人说了,丢了就丢了呗,反正也是缓存数据,持久化数据都在数据库呢。这么说也没毛病,你想想缓存了那么多数据,再从数据库一条一条的加入缓存?假如redis宕机发生在秒杀环节呢?那这么说缓存是不是等于没做?
二、redis持久化方案
redis有两种持久化方案:RDB和AOF
rdb类似一种数据的备份,就是将缓存中的数据冷备份到磁盘。需要恢复直接将改文件放到指定目录下即可。恢复速度快,数据丢失相对较多。
aof就是日志记录,将该redis中发生的所有数据变化记录下来。恢复时就可以通过aof中的日志进行恢复。因为是解析日志,恢复速度慢,但是数据丢失少。
如果同时使用 RDB 和 AOF 两种持久化机制,那么在 redis 重启的时候,会使用 AOF 来重新构建数据,因为 AOF 中的数据更加完整。
2.1 RDB
优点:
- 冷热备:RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷热备。
- 高性能:RDB对redis的对外读写能力影响有限,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO来进行RBD持久化即可。
- 快速恢复:相对AOF持久化机制来说,直接基于RDB的数据恢复更加快速。因为RDB文件就是redis的数据备份。
缺点:
- 数据丢失:如果采用RDB进行数据的备份,数据完整性没有AOF表现的那么好。一般来说RDB数据快照文件是每个5分钟进行一次备份。所以可能会造成5分钟的数据丢失。
- 海量数据阻塞主进程:尽管RDB仅仅是fork一个子进程来执行RDB快照数据文件的备份,如果数据文件特别大,可能导致主进程被阻塞数毫秒甚至是数秒。
2.2 AOF
AOF持久化过程:
1.追加写入
redis将每一条写命令以redis通讯协议添加至缓冲区aof_buf,这样的好处在于在大量写请求情况下,采用缓冲区暂存一部分命令随后根据策略一次性写入磁盘,这样可以减少磁盘的I/O次数,提高性能。
2.同步命令到硬盘
当写命令写入aof_buf缓冲区后,redis会将缓冲区的命令写入到文件,redis提供了三种同步策略,由配置参数appendfsync决定。
优点:
- 数据丢失更少:AOF日志文件每隔一秒会通过fsync刷新到磁盘。所以在默认情况下只会丢失一秒的数据。
- 性能开销小:AOF日志文件即使过大,出现后台重写操作,也不会影响客户端的读写。因为在rewrite log的时候,会对其中的指令进行压缩。创建出一份需要恢复的数据的最小日志出来。在创建新日志文件的时候,老的日志文件还是照常写入。当新的merge后的日志文件ready的时候,在交换新老日志文件即可。
- 灾难性误删除紧急恢复:AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要后台rewrite还没发生,那么就可以立即拷贝AOD文件,将最后一条flushall命令删除,然后再将该AOF文件放回去,然后恢复所有数据。
缺点:
- 性能较低:虽然AOF日志文件采用的是append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,但是相对于RDB持久化来说对redis性能影响还是较高的。每隔一秒执行一次fsync操作,这个开销还是很高的。(联想elasticsearch近实时性)
- 数据恢复慢:因为AOF是基于日志文件的数据恢复,所以相较于RDB数据备份来说数据恢复慢。
三、RDB和AOF的选择
如果对数据完整性要求不高RDF是一种比较好的选择。
如果对数据完整性要求较高,也不要仅仅使用AOF一种方式。毕竟恢复耗时,且基于AOF的数据恢复机制也会导致一些bug出现。
最理想的情况是采用两种方式的结合。AOF来保证数据不丢失,作为数据恢复的第一选择。在需要紧急恢复数据的情况下,可以使用RDB进行一定程度的快速容灾方式。
四、常用配置
RDB持久化配置
Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件之后,我们搜索save,可以看到下面的配置信息:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
RDB在以上配置触发以外,还可以通过以下两种命令进行手动触发:
SAVE:阻塞Redis的服务器进程,直到RDB备份完成。
BGSAVE:Fork出一个子进程来创建RDB文件,不阻塞服务器,进程 lastsave 指令可以查看最近的备份时间。(Copy-on-Write)
AOF持久化配置:
AOF默认是关闭的,可以通过appendonly yes来开启。
appendfsync配置:
- no:不使用fsync方法同步,而是交给操作系统write函数去执行同步操作,在linux操作系统中大约每30秒刷一次缓冲。这种情况下,缓冲区数据同步不可控,并且在大量的写操作下,aof_buf缓冲区会堆积会越来越严重,一旦redis出现故障,数据丢失严重。
- always:表示每次有写操作都调用fsync方法强制内核将数据写入到aof文件。这种情况下由于每次写命令都写到了文件中, 虽然数据比较安全,但是因为每次写操作都会同步到AOF文件中,所以在性能上会有影响,同时由于频繁的IO操作,硬盘的使用寿命会降低。
- everysec:数据将使用调用操作系统write写入文件,并使用fsync每秒一次从内核刷新到磁盘。 这是折中的方案,兼顾性能和数据安全,所以redis默认推荐使用该配置。
参考文献:
https://github.com/hello-shf/advanced-java
如有错误的地方还请留言指正。
原创不易,转载请注明原文地址:https://www.cnblogs.com/hello-shf/p/12059902.html