Redis是一种高级key-value数据库,数据存储在内存中,速度很快是优势,但是紧接着带来的则是数据变化瞬息万变,数据该如何保存呢?这就是今日总结的Redis持久化机制。
正常redis数据是保存在内存中的,若遇到redis宕机或者需要重启等场景,数据就会丢失,所以需要将数据存储,将数据备份到磁盘的过程就叫做redis持久化。
redis安装完成之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。
全称redis database,在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,保存在名字为dump.rdb的二进制文件中。它恢复时 直接将快照文件直接读到内存里;
1、在redis.conf配置文件中,搜索关键字save 则会看到RDB的持久化方式,如下图:
如上图则就是RDB触发的机制,默认值是如上三种情况:
触发条件 | 说明 |
---|---|
save 900 a | 如果900秒内至少1个key发生变化(CUD),则重写rdb文件 |
save 300 10 | 如果300秒内至少10个key发生变化(CUD),则重写rdb文件 |
save 60 10000 | 如果60秒内至少10000个key发生变化(CUD),则重写rdb文件 |
若不想开启,则直接把几个注释掉即可。
除了自动触发,也可以选择手动触发的方式
直接执行save命令,则保存成功。每次执行命令都会将所有的redis内存快照到一个新的rdb文件里,覆盖原有的rdb快照文件。默认的是bgsave方式,异步操作。
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [9:49:44] C:127
$ redis-cli
127.0.0.1:6379> save
OK
COW机制
Copy-On-Write顾名思义,在生成快照的同时,依旧可以正常的处理写命令。
进行rdb文件生成的并非是主进程,而是由主进程fork生成的子进程完成的。主进程依旧是执行数据操作命令。
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [10:26:47] C:127
$ redis-cli
127.0.0.1:6379> bgsave
Background saving started
命令 | save | bgsave |
---|---|---|
IO类型 | 同步 | 异步 |
是否阻塞redis其他命令 | yes | no(在生成子进程调用fork函数会有短暂阻塞) |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要fork子进程,消耗内存 |
RDB,快照功能并不是非常耐久,如果Redis宕机,服务器肯定就会丢失最近写入且未保存到快照中的数据,所以则多了一种新的持久化方式,记录到appendonly.aof中(先写入os cache,定期写到磁盘)
redis.conf文件中,appendonly yes/no 修改为yes即可。
重启redis,则会发现aof文件。
PS:若重启了依旧未发现,则执行如下两个命令:
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [11:43:03]
$ redis-cli config set appendonly yes
OK
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [11:43:20]
$ redis-cli config set save ""
OK
我们执行一个set huo 111的命令,然后查看aof文件:
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [11:47:09]
$ redis-cli
127.0.0.1:6379> set huo 111
OK
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [11:47:29]
$ cat appendonly.aof
*3
$3
set
$3
huo
$3
111
这是一种resp协议格式数据,*后边代表的数字表示该命令有多少参数;
$后边代表的数字代表这个参数有几个字符。
每当服务器常规任务函数被执行、 或者事件处理器被执行时, aof.c/flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作:
两个步骤都需要根据一定的条件来执行, 而这些条件由 AOF 所使用的保存模式来决定, 以下小节就来介绍 AOF 所使用的三种保存模式, 以及在这些模式下, 步骤 WRITE 和 SAVE 的调用条件。
Redis 目前支持三种 AOF 保存模式,它们分别是:
命令 | 说明 |
---|---|
appendfsync always | 有新命令就执行一次,非常慢但是也非常安全 |
appendfsync everysec | 每秒fsync一次,足够快,一般情况下不超过两秒钟的数据 |
appendfsync no | 从不fsync,将数据交由操作系统处理,更快,但是更不安全,不采纳 |
可以通过配置来决定多久fsync到磁盘一次,配置命令依旧再redis.conf中。
# appendfsync always
appendfsync everysec
# appendfsync no
模式 | 对服务器主进程的阻塞情况 |
---|---|
AOF_FSYNC_NO | 写入和保存都由主进程执行,两个操作都会阻塞主进程 |
AOF_FSYNC_EVERYSEC | 写入操作由主进程执行,阻塞主进程。保存操作由子线程执行,不直接阻塞主进程,但保存操作完成的快慢会影响写入操作的阻塞时长。 |
AOF_FSYNC_ALWAYS | 写入和保存都由主进程执行,两个操作都会阻塞主进程 |
AOF 文件通过同步 Redis 服务器所执行的命令, 从而实现了数据库状态的记录, 但是, 这种同步方式会造成一个问题: 随着运行时间的流逝, AOF 文件会变得越来越大。
想象有这样一种场景,比如string的原则性操作,incr
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [11:59:45]
$ redis-cli
127.0.0.1:6379> incr huocount
(integer) 1
127.0.0.1:6379> incr huocount
(integer) 2
127.0.0.1:6379> incr huocount
(integer) 3
127.0.0.1:6379> incr huocount
(integer) 4
127.0.0.1:6379> incr huocount
(integer) 5
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [12:00:22]
$ cat appendonly.aof
$3
huo
$3
111
*2
$4
incr
$8
huocount
*2
$4
incr
$8
huocount
*2
$4
incr
$8
huocount
*2
$4
incr
$8
huocount
*2
$4
incr
$8
huocount
最快的方式不就是设置huocount=5就OK了。也有对应的配置来控制AOF自动重写频率。
#aof文件至少要达到64才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
auto-aof-rewrite-percentage 100
#aof文件自上一次重写后文件大小增长了100%则再次触发重写
auto-aof-rewrite-min-size 64mb
重写进程依旧是主进程fork出一个子进程来执行,不会对redis这种正常命令有太多影响。文件太小也就无所谓重写不重写了,自动重写需要条件符合,所以也肯定就有手动重写的命令: bgrewriteaof
PS :以下会讲述混合模式,我是6.0redis演示,混合模式默认是开启的,所以当我执行了重写命令,aof文件会变为二进制模式,无法再cat查看
命令 | RDB | AOF |
---|---|---|
启动优先级 | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 容易丢失数据 | 根据策略决定 |
各自了解了两种持久化的优缺点,发现混合使用效果更好。Redis 4.0则采用了混合持久化方式。
aof-use-rdb-preamble yes/no
混合持久化AOF文件结构如下:
新操作的命令则会继续以AOF的样式在aof文件中存储,之前的则以RDB的二进制文件存储着。
# huoyajing @ huoyajingdeMBP in /usr/local/redis-6.0.15 [14:15:50]
$ cat appendonly.aof
REDIS0009� redis-ver6.0.15�
redis-bits�@�ctime�w�!aused-mem�po�
aof-preamble���huo�huocount��g�r�ÁwJ*2
*3
$3
set
$6
huohuo
$3
232