Redis数据都是存储在内存中,一旦发生宕机或者断电的情况内存中的数据就会消失,所以数据的本地持久化存储就额外重要。这一节我们来看看Redis的两种持久化方式,RDB和AOF。
我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。
文章目录
RDB方式
save命令
客户端执行一次save命令就会进行一次本地化,保存的目录为配置文件中dir
配置项,保存的文件名为配置文件中dbfilename
配置项,默认是dump.rdb
。
配置文件内容如下:
[root@testmachine redis]# cat redis.conf | grep ^dir
dir /usr/local/redis/
[root@testmachine redis]# cat redis.conf | grep ^dbfilename
dbfilename dump.rdb
执行操作:
127.0.0.1:6380> save
OK
生成本地持久化文件:
[root@testmachine redis]# pwd
/usr/local/redis
[root@testmachine redis]# ll dump.rdb
-rw-r--r-- 1 root root 107 Feb 23 16:37 dump.rdb
相关配置
和持久化相关的配置有下面四个:
-
dbfilename dump.rdb
用来设定持久化文件的名字,通常配置为dump-端口号.rdb
,例如dump-6380.rdb
-
dir /
用来设定持久化文件的保存目录,经过实际测试,这里要放绝对路径。 -
rdbcompression yes
采用压缩的方式进行持久化,保持yes即可 -
rdbchecksum yes
读和写过程中检查文件完整性,保持yes即可
数据的恢复
数据只要被持久化了下来,即使是意外断电,redis服务程序突然中断也不会影响到原始数据。只要在再次启动的时候,使用相同的配置文件,redis会自动将持久化的数据读取到内存中。
save命令的缺点
因为redis是单线程的,假如save命令耗时过长,会导致服务端长时间阻塞,所以线上不建议使用save命令的方式做持久化。
bgsave命令
为了解决save的阻塞问题,引入了bgsave的方式,将持久化的过程在后台进行,不会造成阻塞:
127.0.0.1:6380> bgsave
Background saving started
127.0.0.1:6380>
但是这样也造成了缺点,就是无法在客户端看到保存成功的返回,只能通过查看log来进行验证。
那么如果bgsave中途出错了怎么办,有一个配置项可以进行设置:
- stop-writes-on-bgsave-error yes
如果中途出错就停止写入文件,保持默认的yes即可
服务端自动持久化
除了人为手动去做持久化,还可以让服务端自动操作。根据配置中的save second changes
项来设定条件,满足条件就触发bgsave过程,通常都会设定多个条件配合使用
save 900 1
save 300 10
save 60 10000
上述设定就是在900秒内有一次key更改,或者300秒内有10次key更改,或者60秒内有10000次key更改,都会触发bgsave。可以看到操作越密集,持久化也就越频繁。每次持久化完成以后都会将计时重置。
RDB方式的优缺点
优点:
- RDB是一个紧凑压缩的二进制文件,存储效率较高
- RDB存储的是某时间点的数据快照,非常适合做数据备份
- RDB恢复数据比AOF要快很多
缺点:
- RDB无法做到实时持久化,所以几乎一定会有数据丢失
- bgsave每次都要fork出子进程去完成后台备份,牺牲掉了一些性能
- Redis的各个版本之间的RDB格式存在不兼容的现象
AOF方式
为了解决RDB的缺点,引入了AOF的持久化方式,将备份数据改为备份对数据的操作。
- 每次对数据内容有修改的操作都被记录下来,确保了实时性
- 不需要子进程,节约了性能
- 没有兼容性问题
AOF的三种策略
- always
每一条命令都会进行一次AOF操作,数据完整性最高。但是在操作较频繁,例如每秒几十万次的场景,会涉及到大量IO操作,会大大降低性能 - everysec
每秒进行一次AOF操作,如果出现宕机,会丢失一秒钟的数据,准确性也比较高 - no
由操作系统来控制写入AOF的的时间,不可控
不推荐使用always,除非对数据完整性要求非常高。一般场景用everysec策略即可。
AOF配置项
一共有三个配置项
- appendonly no
开启AOF功能,默认是no,改为yes开启 - appendfilename “appendonly.aof”
配置AOF文件的名字,也是建议配置为appendonly-端口号.aof
的格式。文件的保存目录和RDB中是同一个配置项 - appendfsync everysec
上面提到的三种AOF策略
[root@testmachine redis]# cat redis.conf | grep ^append
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
修改配置重启redis之后在RDB的目录中出现了一个大小为0的文件
[root@testmachine redis]# pwd
/usr/local/redis
[root@testmachine redis]# ll appendonly.aof
-rw-r--r-- 1 root root 0 Feb 23 18:44 appendonly.aof
注意,在配置文件中开启AOF,因为Redis重启后恢复数据优先以AOF来恢复,会导致原先的数据虽然写入了RDB文件,但是重启Redis服务后并没有读到内存中,查询会显示没有任何key。只有当删除了AOF文件并且关闭了AOF功能后才会恢复到RDB中读取。
验证AOF
打开AOF,重启Redis,然后进行操作
127.0.0.1:6380> set a 1
OK
127.0.0.1:6380> set b 2
OK
127.0.0.1:6380>
发现AOF文件大小增加了
[root@testmachine redis]# pwd
/usr/local/redis
[root@testmachine redis]# ll appendonly.aof
-rw-r--r-- 1 root root 77 Feb 23 18:44 appendonly.aof
如果持续修改key,每一秒钟这个文件都会变化一次,文件会越来越大。
AOF重写
这里有一个问题,例如我对一个key先赋值再删除,或者是对一个key更新多遍,AOF还是会原封不动的把命令从头到尾记录一遍,但是其实只有最后一条命令是有意义的。为了消除这些冗余,使得AOF存储和恢复更高效,就需要用到AOF重写。
AOF重写的几条规则:
- 已经过期的数据不再记录
- 按照数据最终的状态进行记录
- 对同一数据的重复操作合并
和RDB一样,既可以手动执行命令完成重写,也可以通过修改配置项让服务端自动完成重写
手动重写
首先删除原先的AOF文件,重启redis服务,达到清除AOF记录的目的
[root@testmachine redis]# rm appendonly.aof
rm: remove regular file ‘appendonly.aof’? y
[root@testmachine redis]# systemctl restart redis
然后我们对同一个key多次操作,故意造成冗余记录
127.0.0.1:6380> set a 1
OK
127.0.0.1:6380> set a 2
OK
127.0.0.1:6380> set a 3
OK
127.0.0.1:6380>
查看下AOF文件
[root@testmachine redis]# ll appendonly.aof
-rw-r--r-- 1 root root 104 Feb 23 20:28 appendonly.aof
[root@testmachine redis]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$1
a
$1
1
*3
$3
set
$1
a
$1
2
*3
$3
set
$1
a
$1
3
然后手动对AOF进行重写,和bgsave一样也是在后台进行的
127.0.0.1:6380> bgrewriteaof
Background append only file rewriting started
127.0.0.1:6380>
过一会再去查看AOF文件
[root@testmachine redis]# ll appendonly.aof
-rw-r--r-- 1 root root 102 Feb 23 20:52 appendonly.aof
发现AOF文件大小确实减小了。
但是再cat的时候,发现AOF里面是乱码,我怀疑是我环境的问题。而且会发现不仅AOF文件变了,RDB文件也变了。
自动重写
配置文件中有两个配置项用来设置自动重写的触发门限:
- auto-aof-rewrite-percentage 100
- auto-aof-rewrite-min-size 64mb
其中第一个是百分比,触发条件为
(aof_current_size - aof_base_size) / aof_base_size = auto-aof-rewrite-percentage
第二个是绝对值,触发条件为
aof_current_size = auto-aof-rewrite-min-size
其中的两个变量可以在客户端通过info Persistence
查看
127.0.0.1:6380> info Persistence
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1582462921
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:167936
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:0
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:139264
aof_current_size:233
aof_base_size:102
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0
127.0.0.1:6380>
百分比和绝对值可以只配置一个,如果将百分比设置为0就是关闭自动重写功能。
RDB和AOF方案对比
持久化方式 | RDB | AOF |
---|---|---|
占用存储空间 | 小 | 大 |
存储速度 | 慢 | 快 |
恢复速度 | 快 | 慢 |
数据安全性 | 会丢失数据 | 根据策略决定 |
资源消耗 | 高 | 低 |
启动优先级 | 低 | 高 |
- 对数据完整性要求比较高的,采用AOF持久化方案
- 数据呈现阶段性有效,且对恢复时间要求较高的,采用AOF持久化方案
- AOF和RDB可以同时打开互不影响,重启后Redis优先采用AOF来恢复数据