redis缓存架构详解(二)-redis持久化-RDB持久化详解

2. redis持久化

接下来,我们讲解redis企业级的持久化方案。

2.1. redis持久化的意义

redis持久化的意义,在于故障恢复。

我们部署redis,作为cache缓存的同时,也可以保存一些较为重要的数据。如果redis没有持久化,redis遇到灾难性故障的时候,就会丢失所有的数据。

​ 通过持久化将数据备份一份到磁盘,然后定期同步和备份到一些云存储服务上去,当redis服务器出现灾难时,就可以从云存储上拉取数据,恢复到新的redis缓存中,保证数据不丢失全部,能恢复一部分数据。

如下图,redis持久化的意义:

在这里插入图片描述

​ 企业级的redis集群架构,支撑海量数据、高并发、高可用,而持久化功能提供的灾难恢复,数据恢复,为redis集群架构的高可用提供有力保障。

​ 当redis整个集群架构挂了,redis就不可用,我们要让redis尽快恢复,提供服务。

​ 1、redis没有做持久化,重启redis后,也不可用,因为没有数据。就会导致大量的请求过来,缓存全部无法命中,就会直接去访问数据库,导致缓存雪崩问题。

​ 2、 redis做了持久化,具备缓存的备份和恢复方案,那么即使redis故障了,也可以通过备份数据,快速恢复,一旦恢复立即对外提供服务。

redis中的数据受内存大小限制,存放数据的量不是无限增长,到一定时间,redis会通过缓存淘汰算法LRU,自动将一部分数据从内存中给清除。     

redis的持久化与系统的高可用是有直接关系。redis持久化主要有RDB,AOF两种方式。

2.2. RDB持久化

2.2.1. RDB原理

RDB 的全称是 Redis database. 顾名思义,RDB 就是将 Redis 数据库,用来存储数据的,所以通过RDB方式持久化,就是将存在Redis内存中的数据周期性的写入到 RDB文件中保存到磁盘上,从而实现持久化的。

​ 既然RDB机制是通过把某个时刻的所有数据生成一个快照来保存,那么就应该有一种触发机制,是实现这个过程。对于RDB来说,提供了三种机制:save、bgsave、自动化。我们分别来看一下

2.2.2. redis生成RDB文件的触发机制

(1) save触发方式

​ 该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。具体流程如下:

在这里插入图片描述

​ 执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。

(2) bgsave触发方式

​ 执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下:

在这里插入图片描述

​ 具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。

save与bgsave的优缺点:

命令 IO类型 阻塞 复杂度 优点 缺点
save 同步 O(n) 不会消耗额外内存 阻塞客户端命令
bgsave 异步 是(阻塞发生在fork,时间很短) O(n) 不阻塞客户端命令 需要fork,消耗内存

(3) 自动触发

自动触发是由我们的配置文件来完成的。在redis.conf配置文件中,里面有如下配置,我们可以去设置:

①save:这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave。

在这里插入图片描述

默认如下配置:

save 900 1 #表示900秒内如果有1个key的值变化,则保存

save 300 10 #表示300秒内如果有10个key的值变化,则保存

save 60 10000 #表示60秒内如果有10000个key的值变化,则保存

不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能。


2.2.3.RDB持久化机制的优点

(1)非常适合做冷备份
RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备,可以将这种完整的数据文件发送到一些远程的云存储上去,如阿里云、亚马逊等,以预定好的备份策略来定期备份redis中的数据。

(2)redis 性能高
使用RDB,使redis对外提供的读写服务影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可。

(3)重启和恢复redis进程,更加快速

​ 相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速。


2.2.4. RDB持久化机制的缺点

(1)丢失数据比AOF严重

​ 如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好。一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,如果redis进程宕机,那么会丢失最近5分钟的数据。

(2)生成RDB文件特别大时,容易导致服务暂停

​ RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒。


2.2.5. RDB持久化配置及数据恢复实验

1、如何配置RDB持久化机制

redis.conf文件,也就是/etc/redis/6379.conf,去配置持久化

save 60 1000

每隔60s,如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting(快照)。

也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成

save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有,就生成一个新的dump.rdb文件


2、RDB持久化机制的工作流程

(1)redis根据配置自己尝试去生成rdb快照文件
(2)fork一个子进程出来
(3)子进程尝试将数据dump到临时的rdb快照文件中
(4)完成rdb快照文件的生成之后,就替换之前的旧的快照文件

dump.rdb,每次生成一个新的快照,都会覆盖之前的老快照


3、基于RDB持久化机制的数据恢复实验

(1)在redis中保存几条数据,立即停掉redis进程,然后重启redis,看看刚才插入的数据还在不在

数据还在,为什么?

带出来一个知识点,通过redis-cli SHUTDOWN这种方式去停掉redis,其实是一种安全退出的模式,redis在退出的时候会将内存中的数据立即生成一份完整的rdb快照

/var/redis/6379/dump.rdb

(2)在redis中再保存几条新的数据,用kill -9粗暴杀死redis进程,模拟redis故障异常退出,导致内存数据丢失的场景

这次就发现,redis进程异常被杀掉,数据没有进dump文件,几条最新的数据就丢失了

(3)手动设置一个save检查点,save 5 1
(4)写入几条数据,等待5秒钟,会发现自动进行了一次dump rdb快照,在dump.rdb中发现了数据
(5)异常停掉redis进程,再重新启动redis,看刚才插入的数据还在

2.3. AOF持久化

​ AOF机制对每条写入命令以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集。

2.3.1. AOF持久化原理

AOF持久化原理如下:

在这里插入图片描述

每当有一个写命令过来时,就直接保存在我们的AOF文件中。

AOF 持久化功能的实现可以分为命令追加( append )、文件写入( write )、文件同步( sync )、文件重写(rewrite)和重启加载(load)。其流程如下:
  • 所有的写命令会追加到 AOF 缓冲中。
  • AOF 缓冲区根据对应的策略向硬盘进行同步操作。
  • 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
  • 当 Redis 重启时,可以加载 AOF 文件进行数据恢复。

2.3.2.文件重写原理

AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。为了压缩aof的持久化文件,redis提供了bgrewriteaof命令,将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写。

在这里插入图片描述

重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

2.3.3.AOF也有三种触发机制

(1)每修改就同步always:同步持久化 每次发生数据变更会被立即记录到磁盘,性能较差,但数据完整性比较好。

(2)每秒同步everysec:异步操作,每秒记录,如果一秒内宕机,有数据丢失。

(3)不同no:从不同步。

always、everysec、no之间的优缺点:

命令 优点 缺点
always 不丢失数据 IO开销大,一般的sata盘只有几百TPS
everysec 每秒一次fsync 丢1秒数据
no 不用管 不可控

2.3.4. AOF持久化机制的优点

(1)AOF可以更好的保护数据不丢失

AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据

(2)写入性能非常高,文件不容易破损

AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复

(3)AOF日志文件过大,也不会影响客户端的读写

AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在rewrite log的时候,会对其中的指导进行压缩,创建出一份需要恢复数据的最小日志出来。再创建新日志文件的时候,老的日志文件还是照常写入。当新的merge后的日志文件ready的时候,再交换新老日志文件即可。

(4)AOF日志文件可读性好,易做灾难性恢复

AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据


2.3.5. AOF持久化机制的缺点

(1)AOF日志文件比RDB大

对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大

(2)AOF文件同步频率高,写入性能相对低

AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的。

(3)AOF基于日志做数据恢复,可能出现与原始数据不一样的错误

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


发布了155 篇原创文章 · 获赞 23 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/makyan/article/details/104727687