Redis第二话——持久化存储机制

Redis的强劲性能主要是依靠其数据都存储在内存中,若redis重启或者服务器故障导致redis重启,所有存储在内存中的数据就会丢失。

但是在某些情况下,我们希望Redis在重启后能够保证数据不会丢失。

  1. 将redis作为nosql数据库使用。
  2. 将Redis作为高效缓存服务器,缓存被击穿后对后端数据库层面的瞬时压力是特别大的,所有缓存同时失效可能会导致雪崩。

这时我们希望Redis能将数据从内存中以某种形式同步到硬盘上,使得重启后可以根据硬盘中的记录来恢复数据。

Redis支持两种方式的持久化,一种是RDB(Redis Database Backup file)方式、另一种是AOF(append-only-file)方式,两种持久化方式可以单独使用其中一种,也可以将这两种方式结合使用。

  • RDB:根据指定的规则“定时”将内存中的数据存储在硬盘上。(即快照)
  • AOF:每次执行命令后将命令本身记录下来。

一、RDB

RDB的实现方式为,在指定时间将当前时刻内存中的数据生成一个快照文件(.rdb文件,默认为dump.rdb),并将这个快照文件保存到磁盘上。

这样,即使redis宕机了,下次重启时也可以通过读取这个快照文件来恢复数据。

触发生成rdb快照文件的方式主要有五种:配置文件自动触发、执行save命令、执行bgsave命令、执行shutdown命令、执行flushall命令。

rdb文件默认文件名为dump.rdb,是在配置文件中配置的如果我们想要修改这个名字可以通过rdbfilename配置修改。

1.配置文件自动触发

redis默认的配置文件redis.conf中,有一个自动触发rdb持久化的配置。

这三行配置默认是被注释掉的,使用时多个条件可组合使用,根据自己的需求按规则来配置

这三行命令的意思是:

save 900 1 -> 900秒内有1个key被修改(写操作),则触发RDB

save 300 100 -> 300秒内有100个key被修改(写操作),则触发RDB

save 60 10000 -> 60秒内有10000个key被修改(写操作),则触发RDB

当满足其中任意一个save条件时,都会触发一次bgsave命令进行异步持久化

2.执行save命令

save命令是一个同步操作,执行该命令后,RDB持久化是在主进程中进行的,这样会阻塞当前redis服务,直到RDB持久化完成后,客户端才能正常连接redis服务。

3.执行bgsave命令

bgsave命令是对save命令的一个优化,是一个异步操作。执行该命令后,redis主进程会通过fork操作创建一个子进程,RDB持久化是由子进程操作,完成后自动结束。

这个过程中,主进程不阻塞,可以继续接收客户端的访问。因此,redis内部所有涉及RDB持久化的操作都是采用的bgsave方式,save命令基本已经废弃。

bgsave的流程可以参考下图:

 

 

4.执行shutdowm命令

shutdown触发方式比较简单,只需要在客户端执行shutdown命令即可。

执行shutdown命令后,自动生成了一个dump.rdb文件

5.执行flushall命令

flushall命令是清空redis内存中的数据,并且同时清空dump.rdb文件。

所以这个命令就相当于删库跑路,此处只是说明该命令会触发rdb,实际使用中千万不要执行。

如果之前没有dump.rdb文件,则执行flushall命令后,会生成一个dump.rdb文件。

如果之前已经存在dump.rdb文件,并且里面也存在数据,那么执行flushall命令后,会将原来dump.rdb文件中的内容清空。

 二、AOF

AOF是redis提供的另一种数据持久化方式,它会记录客户端对redis服务端的每一次写操作,并将这些写操作以redis协议追加保存到后缀为aof的文件末尾。

在redis服务器重启时,会读取并加载aof文件,达到恢复数据的目的。

aof持久化方式redis是默认不开启的,我们可以通过配置文件开启aof持久化方式。

appendonly的值默认为no,改为yes即可开启aof持久化方式。

AOF的默认文件名为appendonly.aof,也可通过appendfilename配置修改。

两个缓冲区:aof_buf 和 aof_rewrite_buf

1. appendfsync always

 

客户端对redis服务器的每次写操作都写入AOF日志文件。这种方式是最安全的方式,但每次写操作都进行一次磁盘IO,非常影响redis的性能,所以一般不使用这种方式。

 

2. appendfsync everysec

 

每秒刷新一次缓冲区中的数据到AOF文件。这种方式是redis默认使用的策略,是考虑数据完整性和性能的这种方案,理论上,这种方式最多只会丢失1秒内的数据。

 

3. appendfsync no

 

redis服务器不负责将数据写入到AOF文件中,而是直接交给操作系统去判断什么时候写入。这种方式是最快的一种策略,但丢失数据的可能性非常大,因此也是不推荐使用的。

 

AOF文件重写

既然AOF是通过日志追加的方式来存储redis的写指令,那么当我们对同一个key做多次写操作时,就会产生大量针对同一个key操作的日志指令,导致AOF文件会变得非常大,恢复数据的时候会变得非常慢。因此,redis提供了重写机制来解决这个问题。redis通过重写AOF文件,保存的只是恢复数据的最小指令集。

我们可以通过下面命令手动触发重写:bgrewriteaof

也可以通过配置文件自动触发重写:

auto-aof-rewrite-percentage 100:当文件的大小达到原先文件大小(上次重写后的文件大小,如果没有重写过,那就是redis服务启动时的文件大小)的两倍。

auto-aof-rewrite-min-size 64mb:文件重写的最小文件大小,即当AOF文件低于64mb时,不会触发重写。

只有这两个指标同时满足的时候才会发生重写。

AOF文件的重写流程如下:

(1)bgrewriteaof触发重写,判断是否存在bgsave或者bgrewriteaof正在执行,存在则等待其执行结束再执行;

(2)主进程fork子进程,防止主进程阻塞无法提供服务;

(3)子进程遍历Redis内存快照中数据写入临时AOF文件,同时会将新的写指令写入aof_buf和aof_rewrite_buf两个重写缓冲区,

 前者aof_buf是为了定期写回旧的AOF文件,后者aof_rewrite_buf是为了后续刷新到临时AOF文件中,防止快照内存遍历时新的写入操作丢失(防止在aof重写过程中新的写入操作丢失);

(4)子进程结束临时AOF文件写入后,通知主进程;

(5)主进程会将上面的aof_rewirte_buf缓冲区中的数据写入到子进程生成的临时AOF文件中;

(6)主进程使用临时AOF文件替换旧AOF文件,完成整个重写过程。

 

三、RDB和AOF对比

RDB的优点:

  1. RDB文件非常紧凑,节省内存空间;
  2. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快;
  3. 适合全量备份、全量复制的场景,经常用于灾难恢复(对数据的完整性和一致性要求相对较低的场合)

RDB的缺点:

  1. 服务器宕机时,可能会丢失部分数据;
  2. 每次保存RDB的时候,Redis都要fork出一个子进程,这个过程是阻塞的,如果数据集巨大,那阻塞的时间就会很长。

AOF的优点:

  1. 数据更加完整,丢失数据的可能性较低;
  2. AOF日志文件可读,并且可以对AOF文件修复。

AOF的缺点:

  1. AOF日志记录在长期运行中逐渐庞大,恢复起来非常耗时,需要定期对AOF日志进行瘦身处理;
  2. 恢复备份速度比较慢。

其他小知识:

官方建议使用RDB持久化或两者共同使用确保数据安全性

目前AOF程序有一些bug

之后会将二者整合成单个持久化模型

 

posted on 2022-09-17 10:50  HHHuskie  阅读(101)  评论(0编辑  收藏  举报

导航