redis持久化的快照(snapshot)方法和AOF方法
redis的持久化主要提供了2种方法,快照(snapshot)方法和AOF(append only)方法,做实验试一下这2种方法。
快照方法是把redis内存中的数据在隔一段时间之后,fork一个子进程,在子进程中将内存中的数据写入存储。当然这种模式下,如果系统异常退出会出现数据的丢失,更严重的是因为要fork子进程,内存的消耗会在短时间内突然倍增。
下面做实验来看一下,先从启动一个空的redis数据库开始
xxxx@xxxx-computer:~$ ps -ef | grep redis xxxx 5071 4168 0 10:12 pts/0 00:00:00 grep --color=auto redis xxxx@xxxx-computer:~$ sudo ls -l /var/lib/redis/dump.rdb -rw-r--r-- 1 root root 18 2月 15 10:11 /var/lib/redis/dump.rdb xxxx@xxxx-computer:~$ sudo cat /var/lib/redis/dump.rdb REDIS0006�ܳC�Z��Vxxxx@xxxx-computer:~$ xxxx@xxxx-computer:~$ sudo redis-server /etc/redis/redis.conf xxxx@xxxx-computer:~$ redis-cli -h localhost -p 6379 redis localhost:6379> keys * (empty list or set) redis localhost:6379> set str1 abcdef OK redis localhost:6379> set num1 123 OK redis localhost:6379> keys * 1) "num1" 2) "str1" redis localhost:6379> quit xxxx@xxxx-computer:~$ redis-cli -h localhost -p 6379 shutdown xxxx@xxxx-computer:~$ sudo ls -l /var/lib/redis/dump.rdb -rw-r--r-- 1 root root 41 2月 15 10:15 /var/lib/redis/dump.rdb xxxx@xxxx-computer:~$ sudo cat /var/lib/redis/dump.rdb REDIS0006�num1�{str1abcdef�O�j'�xxxx@xxxx-computer:~$ xxxx@xxxx-computer:~$ clear
在set数据之后,用正常的方式shutdown redis,redis-cli shutdown,完成之后,在redis的dump文件中会看到操作中set的数据,如果你看到的是乱码,那么应该是你的redis启用了rdb压缩(rdbcompression),默认这一项是启用的,取消就好。在redis.conf中修改配置
# comment by valleylord, origin setting changes
# rdbcompression yes
rdbcompression no
如果是redis非正常退出的话,这个在实验中可以用kill来模拟,如之前所说,可能会出现数据丢失,实验步骤如下
xxxx@xxxx-computer:~$ ps -ef |grep redis xxxx 5192 4168 0 10:20 pts/0 00:00:00 grep --color=auto redis xxxx@xxxx-computer:~$ sudo ls -l /var/lib/redis/dump.rdb -rw-r--r-- 1 root root 41 2月 15 10:15 /var/lib/redis/dump.rdb xxxx@xxxx-computer:~$ sudo cat /var/lib/redis/dump.rdb REDIS0006�num1�{str1abcdef�O�j'�xxxx@xxxx-computer:~$ xxxx@xxxx-computer:~$ sudo redis-server /etc/redis/redis.conf xxxx@xxxx-computer:~$ redis-cli -h localhost -p 6379 redis localhost:6379> keys * 1) "str1" 2) "num1" redis localhost:6379> set str2 wxyz OK redis localhost:6379> keys * 1) "str1" 2) "str2" 3) "num1" redis localhost:6379> get str2 "wxyz" redis localhost:6379> quit xxxx@xxxx-computer:~$ sudo ls -l /var/lib/redis/dump.rdb -rw-r--r-- 1 root root 41 2月 15 10:15 /var/lib/redis/dump.rdb xxxx@xxxx-computer:~$ sudo killall -9 redis-server xxxx@xxxx-computer:~$ sudo ls -l /var/lib/redis/dump.rdb -rw-r--r-- 1 root root 41 2月 15 10:15 /var/lib/redis/dump.rdb xxxx@xxxx-computer:~$ sudo cat /var/lib/redis/dump.rdb REDIS0006�num1�{str1abcdef�O�j'�xxxx@xxxx-computer:~$ xxxx@xxxx-computer:~$ ps -ef| grep redis xxxx 5236 4168 0 10:23 pts/0 00:00:00 grep --color=auto redis xxxx@xxxx-computer:~$ sudo redis-server /etc/redis/redis.conf xxxx@xxxx-computer:~$ redis-cli -h localhost -p 6379 redis localhost:6379> get str2 (nil) redis localhost:6379> keys * 1) "num1" 2) "str1" redis localhost:6379> quit
实验中,继续前一个实验的操作,又设置了str2这个key,然后快速的退出,并用kill杀掉redis-server进程,再次启动发现数据str2丢失。实验的效果与配置项save有关,默认配置如下,我没改
save 900 1 save 300 10 save 60 10000
表示:900秒内,至少有1个key发生变动,那么就写入;以此类推后2条。我刚才的实验中,只修改了1个数据,那么我就需要在900秒内模拟系统异常退出,否则redis还是会写入。
再来看一下AOF持久化方法,AOF的做法是,将每一次数据的变动写入aof文件,然后类似快照产生的方法,fork一个进程来做,这样就不会丢失数据,这个有点类似与oracle的redo log的原理,但是比较弱。使用AOF之后,快照方法就不再适用,同样,rdb文件中的数据也不会再被读入,而是完全用aof文件代替。redis还对aof做了一些优化,比如aof rewrite,如果一个key有多次写入,那么只取最后一次写入。做实验来看一下,AOF如何做到不丢失数据,首先,在配置文件中启用AOF,默认是不启用的
# comment by valleylord, origin setting changes # rdbcompression yes appendonly yes # The name of the append only file (default: "appendonly.aof") appendfilename appendonly.aof
实验的过程如下
xxxx@xxxx-computer:~$ ps -ef | grep redis xxxx 6769 4168 0 15:26 pts/0 00:00:00 grep --color=auto redis xxxx@xxxx-computer:~$ sudo redis-server /etc/redis/redis.conf xxxx@xxxx-computer:~$ redis-cli -h localhost -p 6379 redis localhost:6379> keys * (empty list or set) redis localhost:6379> set str2 xyz OK redis localhost:6379> set num2 98765 OK redis localhost:6379> keys * 1) "str2" 2) "num2" redis localhost:6379> quit xxxx@xxxx-computer:~$ ls -l /var/lib/redis/appendonly.aof -rw-r--r-- 1 root root 89 2月 15 15:27 /var/lib/redis/appendonly.aof xxxx@xxxx-computer:~$ sudo killall -9 redis-server xxxx@xxxx-computer:~$ ps -ef | grep redis xxxx 6854 4168 0 15:29 pts/0 00:00:00 grep --color=auto redis xxxx@xxxx-computer:~$ sudo redis-server /etc/redis/redis.conf xxxx@xxxx-computer:~$ redis-cli -h localhost -p 6379 redis localhost:6379> get str2 "xyz" redis localhost:6379> get num2 "98765" redis localhost:6379> quit xxxx@xxxx-computer:~$
在写入数据之后立刻kill掉redis,模拟意外停止服务,然后重启redis,数据并未丢失。同时也可以看到,在改为AOF之后,第一次启服务的时候,之前设置的str1和num1均丢失了,应为改为AOF之后,系统不再从rdb中读数据。这个跟oracle定时将redo log写会存储的做法还是简单了不少。