RDB
1、RDB持久化
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写
入成功后,再替换之前的文件,用二进制压缩存储。RDB是Redis默认的持久化方式,会在对应的目录下生产一个dump.rdb文件,重启会
通过加载dump.rdb文件恢复数据。
2、开启RDB持久化方式
开启RDB持久化方式很简单,客户端可以通过向Redis服务器发送save或bgsave命令让服务器生成rdb文件,或者通过服务器配置文
件指定触发RDB条件。
- save命令
save命令是一个同步操作。(同步数据到磁盘上)
原理图
当客户端向服务器发送save命令请求进行持久化时,服务器会阻塞save命令之后的其他客户端的请求,直到数据同步完成。
如果数据量太大,同步数据会执行很久,而这期间Redis服务器也无法接收其他请求,所以,最好不要在生产环境使用 save 命令。
save指令相关配置
- bgsave
与save命令不同,bgsave命令是一个异步操作(异步保存数据集到磁盘上)。
原理图
客户端发送bgsave指令到redis服务端,系统调用fork函数,生成子进程,创建rdb文件,完成之后会返回redis服务端消息,告诉
已经保存完毕。
Redis 服务器在BGSAVE 执行期间仍然可以继续处理客户端的请求。
3、符合自定义配置的快照规则(redis.conf)
save:这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如"save m n"。表示m秒
内数据集存在n次修改时,自动触发bgsave。
save m n规则
save m n规则表示每隔m秒,redis中有n个键改变则自动触发bgsave,在redis.conf文件中可以进行配置,并且可以组合使用。
RDB持久化配置:
save m n
#配置快照(rdb)促发规则,格式:save <seconds> <changes>
#save 900 1 900秒内至少有1个key被改变则做一次快照
#save 300 10 300秒内至少有300个key被改变则做一次快照
#save 60 10000 60秒内至少有10000个key被改变则做一次快照
#关闭该规则使用svae “”
dbfilename dump.rdb
#rdb持久化存储数据库文件名,默认为dump.rdb
stop-write-on-bgsave-error yes
#yes代表当使用bgsave命令持久化出错时候停止写RDB快照文件,no表明忽略错误继续写文件。
rdbchecksum yes
#在写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。
dir "/etc/redis"
#数据文件存放目录,rdb快照文件和aof文件都会存放至该目录,请确保有写权限
rdbcompression yes
#是否开启RDB文件压缩,该功能可以节约磁盘空间
启动服务器加载配置文件
redis-server redis.conf 启动服务器时加载配置文件。
RDB优缺点
优点:
- 与AOF方式相比,通过rdb文件恢复数据比较快。
- rdb文件非常紧凑,适合于数据备份。
- 通过RDB进行数据备,由于使用子进程生成,所以对Redis服务器性能影响较小。
缺点
- 如果服务器宕机的话,采用RDB的方式会造成某个时段内数据的丢失,比如我们设置10分钟同步一次或5分钟达到1000次写入就同步一次,那么如果还没达到触发条件服务器就死机了,那么这个时间段的数据会丢失。
- 使用save命令会造成服务器阻塞,直接数据同步完成才能接收后续请求。
- 使用bgsave命令在forks子进程时,如果数据量太大,forks的过程也会发生阻塞,另外,forks子进程会耗费内存。
AOF
AOF(Append Only File)模式做持久化,把所有的写操作命令记录到磁盘文件中保存,也就是说使用AOF会将客户端对于redis的
操作(查询除外)以一个字符串的形式记录到磁盘的文件中去,而在启动redis的时候会去读取这一个文件,将命令执行。
AOF文件与RDB 文件相比不同的是AOF 文件并不是一个snapshot (快照)的概念, 他是一个 append 的概念,文件的信息会直接
添加到文件的末尾,当然这的方式比上面的RDB文件的好处就是,通过调整数据的刷新(同步)方式,是可以做到数据不丢失的,但不利的
地方,即使随着保证数据不丢失的等级升高,对REDIS 本身的性能影响就会越突出。并且AOF 文件是在系统重启动,或者CRASH 后,在
启动REDIS后对系统数据进行恢复的一种方式。
AOF模式的配置方式
redis默认是关闭AOF模式持久化的,需要打开,并且默认是每秒来进行与磁盘的交互,如果要使用需要修改一下redis.conf文件
# 开启aof机制
appendonly yes
# aof文件名
appendfilename "appendonly.aof"
# 写入策略,always表示每个写操作都保存到aof文件中,也可以是everysec或no
appendfsync always
# aof重写期间是否同步,默认使用的是rdb方式no要,开启AOF持久化方式,将 appendonly 修改为 yes。
no-appendfsync-on-rewrite no
# 保存目录
dir ~/redis/
# 重写触发配置
设置重写的基准值,文件达到100%时开始重写(文件是原来重写后文件的2倍时触发)
auto-aof-rewrite-percentage 100
设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写。
auto-aof-rewrite-min-size 64mb
# 加载aof时如果有错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
三种写入策略
在上面的配置文件中,我们可以通过appendfsync选项指定写入策略,有三个选项。
# appendfsync always
# appendfsync everysec
# appendfsync no
1. always
客户端的每一个写操作都保存到aof文件当,这种策略很安全,但是每个写请注都有IO操作,所以也很慢。
2. everysec
appendfsync的默认写入策略,每秒写入一次aof文件,因此,最多可能会丢失1s的数据。
3. no
Redis服务器不负责写入aof,而是交由操作系统来处理什么时候写入aof文件。更快,但也是最不安全的选择,不推荐使用。
AOF文件重写
AOF将客户端的每一个写操作都追加到aof文件末尾,比如对一个key多次执行incr命令,这时候,aof保存每一次命令到aof文件中,
aof文件会变得非常大。
两种重写方式
通过在redis.conf配置文件中的选项no-appendfsync-on-rewrite可以设置是否开启重写,这种方式会在每次fsync时都重写,
影响服务器性以,因此默认值为no,不推荐使用。
重写的触发
方式一: bgrewrite命令
AOF 重写由 Redis 自行触发,bgrewriteaof 仅仅用于手动触发重写操作。
方式二: 配置文件配置自动触发
AOF重写自动触发机制,需要同时满足下面两个条件:auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage
如上述配置表示:当AOF文件的体积大于64Mb,并且AOF文件的体积比上一次重写之久的体积大了至少一倍(100%)时,Redis将执行
bgrewriteaof 命令进行重写。
重写的执行逻辑
(1)bgrewriteaof触发重写,判断是否当前有bgsave或bgrewriteaof在运行,如果有,则等待该命令结束后再继续执行。
(2)主进程fork出子进程执行重写操作,保证主进程不会阻塞。
(3)子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件
完整以及新AOF文件生成期间的新的数据修改动作不会丢失。
(4) 1).子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。
2).主进程把aof_rewrite_buf中的数据写入到新的AOF文件。
(5)使用新的AOF文件覆盖旧的AOF文件,完成AOF重写。
bgrewriteaof执行原理
重写aof文件的好处
1、压缩aof文件,减少磁盘占用量。
2、将aof的命令压缩为最小命令集,加快了数据恢复的速度。
redis重写版本对比
1、redis-4.0版本之前
什么是重写?
假如说我们redis中存了十年的数据,在这十年间就是不断的创建key,删除key,如果最后一次是创建key,没有删除,那么其实前面的
都是可以抵消调的,只需要创建一次key就行了。如果最后一次是删除key,那么这个key就直接不需要创建,因为最终的数据是没有这条数
据的。还有就是如果数据是一个集合类型,那么这十年间不断的往集合中添加元素,删除元素,例如执行了十万次push 1,那么其实最终
可以使用push1个1,来达到相同的效果,前面执行了十万次push操作,而最终恢复数据只用了一次push操作,两个效果相同,很明显执行
一个push的效率比较高。
重写就是抵消和整合命令,删除抵消的命令,合并重复的命令,归属到一个key里面
重写的结果是多条指令合并程一条指令,然后将重写后的指令都放入一个纯指令的日志文件里面。
但是因为日志文件大小是不断增加的,因此如果日志文件非常大的话,那么重写这个过程也是非常耗时的,因此恢复数据仍然很慢。因此在
4.0版本之后进行了改进。
2、redis-4.0版本之后
在4.0之后,重写会将所有的合并后指令放入一个纯指令文件,然后redis会将这个文件中的数据通过rdb的方式写入aof文件中,然后
再将增量的数据以指令的方式append到aof,也就是说间接的出结论:aof当中包含rdb和增量日志。此时aof文件就是一个混合体,即利用
了rdb恢复快,又利用了日志的全量,数据丢失少。如果8点触发,那么就把8点内存里的数据写成 rdb,写到aof文件中,然后8点往后的
所有新的增删改就开始追加。
AOF文件损坏
在写入aof日志文件时,如果Redis服务器宕机,则aof日志文件文件会出格式错误,在重启Redis服务器时,Redis服务器会拒绝载入
这个aof文件,可以通过以下步骤修复aof并恢复数据。
备份现在aof文件,以防万一。
使用redis-check-aof命令修复aof文件,该命令格式如下:
# 修复aof日志文件
$ redis-check-aof -fix file.aof
重启Redis服务器,加载已经修复的aof文件,恢复数据。
AOF的优缺点
优点:
- 备份机制更稳健,丢失数据概率更低。
- AOF文件是一个只进行追加的日志文件,所以不需要写入seek,可通过redis-check-aof工具修复
- AOF文件具有可读性,可以很轻松的分析文件,也可以处理误操作。
缺点:
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
- 恢复备份速度要慢。
- 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。每次读写都同步的话,有一定的性能压力。
混合持久化
redis-4.x后支持了RDB和AOF混合使用。重启redis时,我们很少使用RDB来恢复内存状态,因为会丢失大量数据。我们通常使用AOF
日志重放,但是重放AOF日志性能相对RDB来说要慢很多,这样在redis实例很大的情况下,启动需要花费很长的时间。redis-4.0为了
解决这个问题,带来了一个新的持久化选项——混合持久化。将RDB文件的内容和增量的AOF日志文件存在一起,这里的AOF日志不再是全量
的日志,而是RDB久化开始 到 RDB持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。
redis-4.x混合持久化机制如下图:
RDB+AOF同时使用
同时使用两种持久化功能需要耗费大量系统资源,系统的硬件必须能够支撑运行这两种功能所需的资源消耗,否则会给系统性能带来
影响Redis服务器在启动时,会优先使用AOF文件进行数据恢复,只有在没有检测到AOF文件时,才会考虑寻找并使用RDB文件进行数据恢复当
Redis服务器正在后台生成新的RDB文件时,如果有用户向服务器发送BGREWRITEAOF命令,或者配置选项中设置的AOF重写条件被满足了,
那么服务器将把AOF重写操作 推延到 RDB文件创建完毕之后再执行,以此来避免两种持久化操作同时执行并争抢系统资源同样,当服务器正在
执行BGREWRITEAOF命令时,用户发送或者被触发的BGSAVE命令也会推延到BGREWRITEAOF命令执行完毕之后再执行。
开启混合持久化
-
混合持久化两种方式
1、通过命令行开启
查询是否开启混合持久化可以使用 config get aof-use-rdb-preamble 命令,其中 yes 表示已经开启混合持久化,
no 表示关闭,Redis 5.0 默认值为 yes。 如果是其他版本的 Redis 首先需要检查一下,是否已经开启了混合持久化。
因为在老的版本中,如果触发重写,那么redis需要遍历老的aof文件,该抵消的抵消,该整合的整合,这是一个非常消耗cpu的计算
判断过程。使用这种方式的话,就把cpu判定的过程给取消掉了,直接对用内存对磁盘的aof文件做卸数,将内存的东西持久化,导成rdb这
种方式写入到aof文件中,相当于加快了重写的过程。最终aof文件中同时包含aof和rdb,aof是增量的。成一个混合体了。
查看aof文件,如果开头出现了"redis"这个字符串,则说明这是一个混合文件,如果没有则说明这是一个老的aof文件。
2、通过修改 Redis 配置文件开启
在Redis的根路径下找到redis.conf文件,把配置文件中的 aof-use-rdb-preamble no 改为 aof-use-rdb-preamble yes
混合持久化的加载流程
- 判断是否开启 AOF 持久化,开启继续执行后续流程,未开启执行加载 RDB 文件的流程;
- 判断 appendonly.aof 文件是否存在,文件存在则执行后续流程;
- 判断 AOF 文件开头是 RDB 的格式, 先加载 RDB 内容再加载剩余的 AOF 内容;
- 判断 AOF 文件开头不是 RDB 的格式,直接以 AOF 格式加载整个文件。
原理图
混合持久化优缺点
优点:
混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动,同时结合 AOF 的优点,
有减低了大量数据丢失的风险。
缺点:
AOF 文件中添加了 RDB 格式的内容,使得 AOF 文件的可读性变得很差;兼容性差,如果开启混合持久化,那么此混合持久化 AOF
文件,就不能用在 Redis 4.0 之前版本了。