Redis持久化(RDB、AOF)
为什么要持久化
Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘中,那么一旦服务器进程退出,服务器的数据库状态就会消失(即断电即失)。为了保证数据不丢失,我们需要将
内存中的数据存储到磁盘,以便 Redis 重启时能够从磁盘中恢复原有的数据,而整个过程就叫做 Redis 持久化。
Redis 持久化也是 Redis 和 Memcached 的主要区别之一,因为 Memcached 是不具备持久化功能的。
持久化的几种方式
Redis 持久化拥有以下三种方式:
快照方式
(RDB, Redis DataBase)将某一个时刻的内存数据,以二进制的方式写入磁盘;
文件追加方式
(AOF, Append Only File),记录所有的写操作命令,并以文本的形式追加到文件中;
混合持久化方式
,Redis 4.0 之后新增的方式,混合持久化是结合了 RDB 和 AOF 的优点,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令
以 AOF 的格式存入文件,这样既能保证 Redis 重启时的速度,又能避免数据丢失的风险。
因为每种持久化方案,都有特定的使用场景,让我们先从 RDB 持久化说起吧。
一、什么是RDB,RDB如何实现持久化?
1、什么是RDB?
RDB是Redis Database 的缩写,其作用是在某一个时间点,将Redis存储在内存中的数据生成快照并存储到磁盘等介质上,存在这个磁盘介质上的文件就是RDB文件。“快照”顾名
思义就是好像照相一样保存当时的数据,这里RDB文件是一个二进制的文件,并且是经过压缩的。因为RDB文件是保存在硬盘中的,即使Redis服务器进程退出,甚至运行Redis
服务器的计算机宕机,但只要RDB文件仍然存在,Redis服务器就可以用它来还原数据库状态。
2、触发方式(手动、自动)
RDB 的持久化触发方式有两类:一类是手动触发,另一类是自动触发。
1)手动触发
(执行 save 或者 bgsave 命令)
手动触发持久化的操作有两个命令: save 和 bgsave ,它们主要区别体现在:是否阻塞 Redis 主线程的执行
。
save命令
redis 127.0.0.1:6379> SAVE
在客户端中执行 save 命令,就会触发 Redis 的持久化,但同时也是使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令,
所以在生产环境一定要慎用
。
![](https://img2020.cnblogs.com/blog/1090617/202112/1090617-20211213182709456-2080680322.jpg)
bgsave命令
redis 127.0.0.1:6379> BGSAVE
bgsave(background save)既后台保存的意思, 它和 save 命令最大的区别就是 bgsave 会 fork() 一个子进程来执行持久化,整个过程中只有在 fork() 子进程时有短暂的
阻塞,当子进程被创建之后,Redis 的主进程就可以响应其他客户端的请求了,相对于整个流程都阻塞的 save 命令来说,显然 bgsave 命令更适合我们使用。
![](https://img2020.cnblogs.com/blog/1090617/202112/1090617-20211213182730834-1553338969.jpg)
在快照进行的过程中,也就是生成文件的过程中,不会对原有的RDB文件进行修改,直到快照生成完毕,直接将老的替换成新的,保证rdb文件任何时刻都是完整的。
2) 自动触发
自动触发的含义就是不用我们手动命令去触发持久化,而是通过配置当满足某一规则的时候自动去执行 bgsave 命令。
Redis的配置文件就默认设置了3个保存点:
# 以下配置表示的条件:
# 900秒内有1个key发生了变化,则触发保存RDB文件
save 900 1
# 服务器在300秒之内被修改了10次
save 300 10
# 服务器在60秒之内被修改了10000次
save 60 10000
#如果想禁用快照保存的功能,可以通过注释掉所有"save"配置达到,或者在最后一条"save"配置后添加如下的配置:
save ""
注意这里满足条件执行的是bgsave
命令。
二、什么是AOF,AOF如何实现持久化?
1、什么是AOF?
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,
换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作 。
默认情况下,redis是没有开启AOF(append only file)的。开启AOF功能需要设置配置:appendonly yes 。
2、AOF持久化流程
上面提到了AOF持久化的过程就是日志不断追加的过程,这里通过图 给大家介绍具体流程:
![](https://img2020.cnblogs.com/blog/1090617/202112/1090617-20211213182755764-768764946.jpg)
1、Client作为命令的来源,会有多个源头以及源源不断的请求命令。
2、在这些命令到达Redis Server 以后,并不是直接写入AOF文件,会将其这些命令先放入AOF缓存中进行保存。这里的AOF缓冲区实际上是内存中的一片区域,存在的目
的是当这些命令达到一定量以后再写入磁盘,避免频繁的磁盘IO操作。
3、AOF缓冲会根据对应的策略
将命令写入磁盘上的AOF文件。
4、AOF文件随着写入文件内容的增加,会根据规则进行命令的合并,这里叫做AOF重写
,从而起到AOF文件压缩的目的。
5、当Redis Server 服务器重启的时候会从AOF文件载入数据。
这里面有两点需要在详细写: AOF缓冲区同步文件策略 和 AOF重写机制。
3、AOF缓冲区同步文件策略
上面提到了Redis 会将命令先写入到AOF缓冲区,再写入AOF文件。这里介绍一下AOF缓冲区同步文件的三个策略。
#aof持久化策略的配置
appendfsync always #always表示每次写入都执行fsync,以保证数据同步到磁盘
appendfsync everysec #everysec表示每秒执行一次fsync,可能会导致丢失这1s数据
appendfsync no #no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快
Always策略 的同步操作是在主进程的主线程中进行的,由于fsync的阻塞特性,会导致其挂起,在此期间无法服务新的请求,因而吞吐量下降,但确实能够保证内存和硬盘中
数据的一致性。
Everysec策略 的同步操作是通过后台I/O线程进行的,由于是在子线程中进行,所以主线程并不会被阻塞,可以继续服务新的请求,但是内存和硬盘中的数据会有1秒的差别
(不一定精准),这是一种折衷的方案,寻求了一个平衡。
No策略 则是将同步操作的控制权交由操作系统,不阻塞主线程,但是数据一致性可能会偏差很大
官方建议使用默认配置每秒同步,它既快速又安全。这个always策略在实践中非常缓慢, 没有办法做得fsync比现在更快。
4、AOF重写机制
(1)是什么?
AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩, 只保留可以恢复
数据的最小指令集。
举个例子:比如有个key 一开始你 set key 1,然后改成 set key 2,最后 set key 3。如果不重写那么这3条语句都在文件中,这样即占空间,启动的时候都要执行一遍无效
的命令,如果重写后,只需要保存set key 3 就可以了。
AOF重写不仅降低了文件的占用空间,同时更小的AOF也可以更快地被Redis加载。
(2)触发机制(手动、自动)
手动:客户端向服务器发送bgrewriteaof命令
自动:满足配置文件中的选项后,自动执行bgrewriteaof命令。Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时
触发。
(3)重写原理
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,
并没有读取旧的aof文件, 而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。
三、RDB和AOF各自优缺点
1、RDB的优点
(1)比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
(2)RDB文件是一个很简洁的单文件,它保存了某个时间点的Redis数据,很适合用于做备份。
(3)RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
2、RDB缺点
(1)RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到Redis出现问题这段时间的数据就会丢失了。
(2)RDB使用fork()产生子进程的过程会堵塞主进程,所以数据比较大的话 fork() 可能很耗时,就会造成Redis停止服务几毫秒。
3、AOF优点
(1)该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常
高的,如果发生灾难,您只可能会丢失1秒的数据。
(2)AOF日志文件是一个纯追加的文件。就算服务器突然Crash,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,
我们也可以用redis-check-aof这个工具很简单的进行修复。
(3)当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行。
4、AOF缺点
(1)在相同的数据集下,AOF文件的大小一般会比RDB文件大。
(2)AOF开启后,写QPS会比RDB的低。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
四、生产配置持久化的一些意见
(1)官方建议:是同时开启两种持久化策略。因为有时需要RDB快照是进行数据库备份,更快重启以及发生AOF引擎错误的解决办法。(换句话就是通过RDB来多备份一份数据
总是好的)
(2) 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
(3)如果选择AOF,只要硬盘许可,应该尽量减少AOF rewrite的频率。因为一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞
几乎是不可避免的。AOF重写的基础大小默认值64M太小了,可以设到2G以上。