Redis数据持久化
RDB方式与AOF方式,可以单独用一种或两种结合。RDB方式相当于定时全备,AOF方式相当于重做日志。
REDIS在RDB与AOF都开启的情况下,启动的时候会加载AOF,因为AOF持久化方式可能丢失的数据更少。
RDB方式
这种持久化是通过快照完成的,当符合一定条件时Redis会自动将内存中的所有数据进行快照,并存储在硬盘上。
进行快照的条件由两个参数构成:save <seconds> <changes>
多个save条件之间是“或”的关系,seconds与changes之间是“与”的关系。
当条件为真,块照会被触发,然后在dir参数定义的目录,以dbfilename参数定义的文件名(一般是dump.rdb)保存下来。
举例:
save 900 1 #900秒内1个key被改动
save 300 10 #300秒内10个key被改动
save 60 10000 #60秒内10000个key被改动
时间最大的一个save后必须是1,假如是比1大的值,比如2,那么只要我每900秒内只改动1个key,那么就永远不会触发快照。
如果想取消这种持久化方式,所有SAVE参数删除或用一条save ""即可。
快照过程:
1. Redis函数使用fork函数赋值一份当前进程的副本(子进程);
2.父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;
3.当子进程写完所有数据后,会用临时文件替换RDB文件,至此一次快照操作完成。
注意:
- 只有快照结束才会将旧的文件替换成新,所以任何时候RDB文件都是完整可用的。
- 新的RDB文件是开始执行fork一刻的内存数据。
- RDB文件是经过压缩的,可以通过配置rdbcompression参数为no以禁用压缩、以节省CPU资源,压缩后的文件更小更利于传输。
- 可以手动用SAVE命令或BGSAVE命令让Redis执行快照,前者由主线程做快照会堵塞其他请求,后者通过fork出子进程进行。
- Redis启动后会读取RDB快照文件,将数据从硬盘载入内存,一般一千万个string,1G的快照需要20-30秒。
查看fork出的子进程
[ldh@hauser redis-2.8.3]$ redis-cli -p 6389 -a pass1234 bgsave && ps -ef | grep redis
Background saving started
ldh 31080 30072 0 11:46 pts/3 00:00:00 redis-server *:6389
ldh 31304 31080 0 11:53 pts/3 00:00:00 redis-rdb-bgsave *:6389
AOF方式
开启AOF持久化后,每执行一条会更改Redis中数据的命令,Redis就会将该命令写入硬盘中的AOF文件。这种写是异步的,通过后台进程处理。默认情况下AOF方式没有开启,可以通过appendonly参数设为yes来开启。AOF文件的保存位置和RDB文件位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof,可以通过appendfilename参数修改。
事实上,appendonly.aof是纯文本格式,打开后也能轻易看懂我们做过的操作。随着执行命令的增多,AOF文件会变得越来越大。所以我们希望删除其中没用的条目。
例如
set foo 1
set foo 2
set foo3
第3条的效果会覆盖前两条,我们只需要保留第三条即可。实际上,我们通过设置这两个参数,来使文件达到条件就自动重写。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
实例启动后,会记得首次rewrite完后文件大小。例如是100mb,那么下次要到200mb,我们才超出100%,才会rewrite。如果实例启动以来还没rewrite过,那么启动时文件多大,就作为上次rewrite数。
这里为了防止文件太小也rewrite,例如上次是10mb,这次到了20mb就rewrite,规定了必须得到64mb以上才能进行rewrite操作。将percentage设为0,可以禁用rewrite特性。
其实rewrite的时候,调用的命令是BGREWRITEAOF,我们也可以手工调用它来执行rewrite。rewrite完后,冗余的数据就被删除了。启动时,redis会将AOF文件中的每条命令载入内存,可以想象,速度肯定比RDB会慢一些。
缓存同步
上述所谓的写到条目写到aof文件,往往其实只是写到OS的缓存。默认情况下系统30秒执行一次同步操作,以便将缓存真正写入磁盘。难道我们AOF必须忍受最高30秒内的数据损失?我们通过appendfsync参数设置同步时机。在一定时机,redis会用fsync()系统调用来通知系统将缓存同步到磁盘。
# appendfsync always --aof文件每有写入就通知系统同步缓存
appendfsync everysec --每秒,安全性与快捷性的折衷
# appendfsync no --交给OS自己决定同步缓存时机