前言
Redis主要是工作在内存中。内存本身就不是一个持久化设备,断电后数据会清空。所以Redis在工作过程中,如果发生了意外停电事故,如何尽可能减少数据丢失?那么就需要持久化,redis中的共有两种持久化方式 RDB和AOF。
Redis 持久化
redis 提供了不同级别的持久化方式:
- RDB持久化方式能够在指定的时间间隔能对数据进行快照存储。
- AOF持久化方式记录每次对服务器写操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾,redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
- 如果只希望数据在服务器运行的时候存在,也可以不使用任何持久化方式。
- 可以同时开启两种持久化方式,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
RDB[默认:开启]
方式:每隔一段时间将redis内存中的数据落盘保存
优点:
1.RDB保存的是直接的数据,占用的存储空间相对于AOF比较少。
2.RDB因为保存的是数据,恢复起来比AOF更快,一般用于容灾恢复(占用空间比较小,可以方便上传到云服务器,即使本地磁盘损坏,也不会对数据产生影响)。
缺点:
由于RDB是每隔一段时间才进行数据落盘,这样可能造成最后最后一段时间内的数据丢失。
RDB有两种持久化方式:
- 主动备份(命令的方式)
- FLUSHALL:清空所有数据后再保存,所以并没有真正的保存数据。
127.0.0.1:6379> set k1 22
OK
127.0.0.1:6379> FLUSHALL
OK
4540:M 16 Jun 11:31:09.131 * Background saving started by pid 4709
4709:C 16 Jun 11:31:09.137 * DB saved on disk
4709:C 16 Jun 11:31:09.137 * RDB: 6 MB of memory used by copy-on-write
4540:M 16 Jun 11:31:09.240 * Background saving terminated with success
4540:M 16 Jun 11:31:15.463 * DB saved on disk
重新启动
127.0.0.1:6379> keys *
(empty list or set)
- SHUTDOWN SAVE
127.0.0.1:6379> set k1 333
OK
127.0.0.1:6379> SHUTDOWN SAVE
4764:M 16 Jun 11:38:03.872 # User requested shutdown...
4764:M 16 Jun 11:38:03.872 * Saving the final RDB snapshot before exiting.
4764:M 16 Jun 11:38:03.872 * DB saved on disk
4764:M 16 Jun 11:38:03.872 * Removing the pid file.
4764:M 16 Jun 11:38:03.872 # Redis is now ready to exit, bye bye..
重新启动
[admin@hadoop102 redis]$ redis-server redis.conf
[admin@hadoop102 ~]$ redis-cli -a 123321
127.0.0.1:6379> get k1
"333"
既然有 SHUTDOWN SAVE 就会有 SHUTDOWN NOSAVE
- SAVE
127.0.0.1:6379> set k2 222
OK
127.0.0.1:6379> save
OK
- BGSAVE
127.0.0.1:6379> set k3 333
OK
127.0.0.1:6379> bgsave
Background saving started
总结:
共有四种命令能够手动触发 RDB 。
- FLUSHALL []
- SHUTDOWN SAVE 或者 SHUTDOWN []
- SAVE
- BGSAVE
RDB持久化原理:
会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
SAVE 与 BGSAVE 区别:
SAVE :复制的进程独享资源,专门进行持久化,会占用主进程资源,此时主进程无法进行客户端的读写。
BGSAVE:复制的进程与主进程共享资源,主进程可以正常完成客户端的读写。
简单说明:SAVE 是同步操作,BGSAVE是异步操作。
- 被动备份(配置文件)
save time change [在time时间范围内操作change次就自动触发RDB持久化。]
# save ""
save 900 1 # 表示 900 秒内 只要有1次对key的写操作就会触发持久化
save 300 10 # 表示 300 秒内 只要有10次对key的写操作就会触发持久化
save 60 10000 # 表示 60 秒内 只要有10000 次对key的写操作就会触发持久化
... # 可以自定义规则,格式:save time change
save "" :表示关闭RDB持久化
RDB 相关文件配置:
是否在备份出错时,继续接受写操作[如果用户开启了RDB快照功能,那么在redis持久化数据到磁盘时如果出现失败,默认情况下,redis会停止接受所有的写请求]
stop-writes-on-bgsave-error yes
是否开启文件压缩[如果开启压缩,那么redis会采用LZF算法进行压缩]
rdbcompression yes
是否进行数据校验[redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗]
rdbchecksum yes
RDB 持久化文件名:
dbfilename dump.rdb
RDB快照保存的目录[必须是一个目录,不能是文件名。最好改为固定目录。默认为./代表执行redis-server命令时的当前目录!]
dir ./
AOF[默认:关闭]
方式:将写操作指令以日志的形式保存
如何开启AOF?
打开配置文件,修改配置
# 是否开启 aof 持久化 no/yes
appendonly no
# aof持久化文件 保存到当前文件。
appendfilename "appendonly.aof"
AOF持久化触发条件
# appendfsync always
appendfsync everysec
# appendfsync no
appendfsync always:将每一个写操作进行持久化,
好处:最多只丢失一条指令数据
坏处:频繁的操作会带来额外的资源开销。
appendfsync everysec:按秒进行持久化
好处:保证数据安全的情况下,一定程度上减少资源开销。
坏处:若服务器出现问题,依旧会丢失一秒的数据。
appendfsync no:不持久化,交给系统来完成
优势:
- AOF相对于RDB而言丢失数据更少,
- 恢复起来更加容易
缺点:
- 由于AOF 保存的是操作指令,相对于RDB而已,需要更多存储空间。
AOF使用:
- 插入三条数据
127.0.0.1:6379> set k22 v22
OK
127.0.0.1:6379> set k33 v33
OK
127.0.0.1:6379> set k44 v44
OK
- 查看 appendonly.aof 文件
[admin@hadoop102 redis]$ cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$3
k22
$3
v22
*3
$3
set
$3
k33
$3
v33
*3
$3
set
$3
k44
$3
v44
选择的是0号库
$6 #表示 SELECT 长度
SELECT
$1 # 表示 0 的长度
0
对key 设值
$3 # set 的字符长度
set
$3 # k22 字符的长度
k22
$3 # v22 字符的长度
v22
其他的意思都差不多。
由此可以更加明显的看出AOF 存储的是写的指令,对于读操作是不会持久化化的。如 get ...
读操作
127.0.0.1:6379> mget k22 k33 k44
1) "v22"
2) "v33"
3) "v44"
重新查看 appendonly.aof 文件
[admin@hadoop102 redis]$ cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$3
k22
$3
v22
*3
$3
set
$3
k33
$3
v33
*3
$3
set
$3
k44
$3
v44
由于RDB进行了压缩,所以没办法查看(及时关闭了压缩,也看不了)。
[admin@hadoop102 redis]$ cat dump.rdb
REDIS0007 redis-ver3.2.5
redis-bitseused-memHþk2k1ÿЇTU©[atguigu@hadoop102 redis]$ XshellXshellXshell
既然AOF 存储的是命令,那么我们去修改一下可以吗?
比如:k22 对应 v22 ,修改 appendonly.aof 改成了v22update看看效果。
修改appendonly.aof,
[admin@hadoop102 redis]$ cat appendonly.aof |grep v22
v22update
重启redis服务
重新连接redis服务:get k22
127.0.0.1:6379> get k22
"v22update"
有什么用呢?试想一下万一不小心执行了FLUSHALL指令,可以直接将FLUSHALL相关的操作在appendonly.aof 中删除就可以完成数据恢复了。可以试一下
清除数据
127.0.0.1:6379> keys *
1) "k44"
2) "k33"
3) "k22"
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$3
k22
$9
v22update
*3
$3
set
$3
k33
$3
v33
*3
$3
set
$3
k44
$3
v44
*2
$6
SELECT
$1
0
*1
$8
flushall
删除这一段,即可完成数据恢复
*2
$6
SELECT
$1
0
*1
$8
flushall
重启并重新连接
127.0.0.1:6379> keys *
1) "k33"
2) "k44"
3) "k22"
关于AOF与RDB优缺点:https://www.jianshu.com/p/257d520003e9
最后:
如果AOF文件中出现了残余命令,会导致服务器无法重启。此时需要借助redis-check-aof工具来修复!
命令: redis-check-aof --fix 文件
网友评论