需求
- RDB的持久化配置和相关的数据恢复实验
- AOF的持久化配置和相关的数据恢复实验
RDB的持久化配置和相关的数据恢复实验
- 配置.
1.登录redis服务器,进入redis安装目录:
cd /usr/local/redis-3.2.8
vi redis.conf
2.找到如下的信息:
save 900 1
save 300 10
save 60 10000
命令 save 300 10的含义是每隔300s,如果有超过10个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting,快照。
也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成。
save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有,就生成一个新的dump.rdb文件。
注意:dump.rdb,每次生成一个新的快照,都会覆盖之前的老快照。
3.在上方配置文件的信息处,重新添加一个检查点,保存退出,信息如下:
save 10 1
4.RDB文件备份过程:
1. redis根据配置自己尝试去生成rdb快照文件。
2. fork一个子进程出来。
3.子进程尝试将数据dump到临时的rdb快照文件中。
4. 完成rdb快照文件的生成之后,就替换之前的旧的快照文件。
- 实验.
1.启动redis服务。
cd /usr/local/redis-3.2.8/src
./redis-server ../redis.conf
2.查看对应的redis服务是否已经启动:
[root@eshop-cache01 src]# ps -ef|grep redis
root 1325 1 0 06:50 ? 00:00:00 ./redis-server 127.0.0.1:6379
root 1338 1191 0 06:51 pts/0 00:00:00 grep redis
3.登录redis,set几个值:
[root@eshop-cache01 src]# ./redis-cli
127.0.0.1:6379> get all
(nil)
127.0.0.1:6379> set key1 val1
OK
127.0.0.1:6379> set key2 val2
OK
127.0.0.1:6379> set key2 val2
4.迅速 kill-9 掉对应的redis服务的进程1325:
kill -9 1325
5.查看对应的redis服务是否已经停止,如下信息就代表已经停止:
[root@eshop-cache01 run]# ps -ef|grep redis
root 1375 1191 0 07:12 pts/0 00:00:00 grep redis
6.删除对应的redis的pid文件(不是正常停止的,pid文件依然存在,重新启动会报错):
[root@eshop-cache01 run]# pwd
/var/run
[root@eshop-cache01 run]# rm redis_6379.pid
rm: remove regular file `redis_6379.pid'? yes
[root@eshop-cache01 run]#
7.重新启动redis服务,登录对应服务,发现之前设置的redis的值,已经不存在:
[root@eshop-cache01 src]# ./redis-server ../redis.conf
[root@eshop-cache01 src]# ps -ef|grep redis
root 1387 1 0 07:53 ? 00:00:00 ./redis-server 127.0.0.1:6379
root 1391 1303 0 07:53 pts/1 00:00:00 grep redis
[root@eshop-cache01 src]# ./redis-cli
127.0.0.1:6379> get key1
(nil)
127.0.0.1:6379> get key2
(nil)
127.0.0.1:6379>
8.重新往redis中设置几个值,并用命令shutdown调对应的redis服务:
127.0.0.1:6379> set key1 val
OK
127.0.0.1:6379> set key2 va2
OK
127.0.0.1:6379> shutdown
not connected>
9.重新启动redis服务,查看对应的数据依然存在:
[root@eshop-cache01 src]# ./redis-server ../redis.conf
[root@eshop-cache01 src]# ps -ef |grep redis
root 1415 1 0 08:04 ? 00:00:00 ./redis-server 127.0.0.1:6379
root 1419 1191 0 08:04 pts/0 00:00:00 grep redis
[root@eshop-cache01 src]# ./redis-cli
127.0.0.1:6379> get key1
"val"
127.0.0.1:6379> get key2
"va2"
127.0.0.1:6379>
- 结论.
1.redis突然出现服务异常(比如直接kill-9)时,RDB持久化方式会导致设置的检查点内的数据丢失。
2.redis的shutdown命令,是一个安全的退出redis的方式。
AOF的持久化配置和相关的数据恢复实验
- 配置.
1.登录redis服务器,进入redis安装目录:
cd /usr/local/redis-3.2.8
vi redis.conf
2.找到如下的信息:
appendonly no
3.将配置修改为如下内容,保存退出:
appendonly yes
注意:AOF日志redis默认是关闭的,必须要通过配置打开。打开AOF持久化机制之后,redis每次接收到一条写命令,就会写入日志文件中,当然是先写入os cache的,然后每隔一定时间再fsync一下。而且即使AOF和RDB都开启了,redis重启的时候,也是优先通过AOF进行数据恢复的,因为aof数据比较完整。
4.AOF的三种fsync策略:
(1).always: 每次写入一条数据,立即将这个数据对应的写日志fsync到磁盘上去,性能非常非常差,吞吐量很低; 确保说redis里的数据一条都不丢,那就只能这样了。
(2). everysec: 每秒将os cache中的数据fsync到磁盘,这个最常用的,生产环境一般都这么配置,性能很高,QPS还是可以上万的,redis默认启用的是此种策略。
(3). no: 仅仅redis负责将数据写入os cache就撒手不管了,然后后面os自己会时不时有自己的策略将数据刷入磁盘,不可控了。
- 实验.
通过第一个RDB的数据实验,我们知道,仅仅只有RDB数据的时候,往redis中设入值后,再kill -9掉对应的redis服务,容易导致数据的丢失。现在我们启用AOF日志策略后,再进行相同的操作,看看对应数据是否会丢失。
1.登录redis服务器,进入redis安装目录:
cd /usr/local/redis-3.2.8/src
[root@eshop-cache01 src]# ./redis-server ../redis.conf
[root@eshop-cache01 src]# ps -ef|grep redis
root 1437 1191 0 09:38 pts/0 00:00:00 vi ../redis.conf
root 1456 1 0 10:03 ? 00:00:00 ./redis-server 127.0.0.1:6379
root 1460 1303 0 10:04 pts/1 00:00:00 grep redis
[root@eshop-cache01 src]# ./redis-cli
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set key1 val1
OK
127.0.0.1:6379> set key2 val2
OK
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
127.0.0.1:6379>
2.立刻杀死redis对应的进程:
[root@eshop-cache01 src]# kill -9 1456
[root@eshop-cache01 src]# ps -ef|grep redis
root 1462 1303 0 10:05 pts/1 00:00:00 ./redis-cli
root 1466 1191 0 10:09 pts/0 00:00:00 grep redis
[root@eshop-cache01 src]#
3.删除对应的redis的pid文件(不是正常停止的,pid文件依然存在,重新启动会报错):
[root@eshop-cache01 run]# pwd
/var/run
[root@eshop-cache01 run]# rm redis_6379.pid
rm: remove regular file `redis_6379.pid'? yes
[root@eshop-cache01 run]#
4.重新启动redis服务,登录对应服务,发现之前设置的redis的值,依然存在:
[root@eshop-cache01 src]# ./redis-server ../redis.conf
[root@eshop-cache01 src]# ps -ef|grep redis
root 1471 1 0 10:11 ? 00:00:00 ./redis-server 127.0.0.1:6379
root 1476 1303 0 10:11 pts/1 00:00:00 grep redis
[root@eshop-cache01 src]# ./redis-cli
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
127.0.0.1:6379>
注意:其实你在appendonly.aof文件中,可以看到刚写的日志,它们以指令的形式存放在aof文件中,可以直接打开查看,所以这也表明aof文件是一个指令文件,不是rdb的数据快照。而且文件中的数据其实就是先写入os cache的,然后1秒后才fsync到磁盘中,只有fsync到磁盘中了,才是安全的,要不然光是在os cache中,机器只要重启,就什么都没了。kill -9杀掉redis进程,重新启动redis进程,发现数据被恢复回来了,就是从AOF文件中恢复回来的。记住,即便是配置了everysec策略,也不能完全保证数据不丢失,依然会丢失1s的数据。想要数据不丢失,只能够设置always策略,但是生产环境不建议如此,性能太差。
- AOF rewrite说明
1.redis中的数据其实有限的,很多数据可能会自动过期,可能会被用户删除,可能会被redis用缓存清除的算法清理掉。
redis中的数据会不断淘汰掉旧的,就一部分常用的数据会被自动保留在redis内存中。所以可能很多之前的已经被清理掉的数据,对应的写日志还停留在AOF中,AOF日志文件就一个,会不断的膨胀,到很大很大。
所以AOF会自动在后台每隔一定时间做rewrite操作,比如日志里已经存放了针对100w数据的写日志了; redis内存只剩下10万; 基于内存中当前的10万数据构建一套最新的日志,到AOF中; 覆盖之前的老日志; 确保AOF日志文件不会过大,保持跟redis内存数据量一致。
2.redis 2.4之前,还需要手动,开发一些脚本,crontab,通过BGREWRITEAOF命令去执行AOF rewrite,但是redis 2.4之后,会自动进行rewrite操作。
3.在redis.conf中,可以配置rewrite策略:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
上面配置的说明:
比如说上一次AOF rewrite之后,是128mb。然后就会接着128mb继续写AOF的日志,如果发现增长的比例,超过了之前的100%,256mb,就可能会去触发一次rewrite。但是此时还要去跟min-size,64mb去比较,256mb > 64mb,才会去触发rewrite。
4.aof日志的过程
- redis fork一个子进程。
- 子进程基于当前内存中的数据,构建日志,开始往一个新的临时的AOF文件中写入日志。
- redis主进程,接收到client新的写操作之后,在内存中写入日志,同时新的日志也继续写入旧的AOF文件。
- 子进程写完新的日志文件之后,redis主进程将内存中的新日志再次追加到新的AOF文件中。
- 用新的日志文件替换掉旧的日志文件。
所以,aof文件始终只有一个。
RDB和AOF同时工作
如果RDB在执行snapshotting操作,那么redis不会执行AOF rewrite; 如果redis再执行AOF rewrite,那么就不会执行RDB snapshotting。
如果RDB在执行snapshotting,此时用户执行BGREWRITEAOF命令,那么等RDB快照生成之后,才会去执行AOF rewrite。
同时有RDB snapshot文件和AOF日志文件,那么redis重启的时候,会优先使用AOF进行数据恢复,因为其中的日志更完整。
对于以上三点,可以简单的做个小实验,就是同时开启rdb和aof,然后设置一些值后,关闭redis,清空对应的aof文件中的指令,然后再启动redis,发现rdb文件中虽然存在数据,但是redis内存中已经不存在数据了。具体的演示我就不做了,想要验证的可以试试看。