Redis提供了两种持久化的方式:
- RDB(Redis DataBase)
- AOF(Append Of File)
一、RDB
1)原理
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot,它恢复时是将快照文件直接读到内存。
Redis会单独创建一个子进程进行持久化操作,会先将数据写入到一个临时文件中,等持久化进程都结束了,再用这个临时文件覆盖(替换)上次持久化好的文件。
整个过程中,由于数据是由父子进程共享的,所以父进程并不需要向子进程传递数据,所以在整个过程中,父进程是没有任何IO操作的,这就保证了极高的性能。在进行大规模的数据的复时,redis对恢复数据的完整性不是非常敏感,虽然RDB方式要比AOF方式更加高效,但是数据的安全性得不到保障。处于效率考虑,Linux中引入了写时复制技术,一般情况下,父子进程共享同一块物理内存,只有当进程空间的各段内容要发生变化时,才会将父进程的内容复制给子进程,此时两者占有的物理内存就不一样了。
关于Linux的COW:https://www.cnblogs.com/biyeymyhjob/archive/2012/07/20/2601655.html
2)RDB保存文件细节
RDB持久化是默认开启的(而AOF不是),你开一在redis.conf中看到这样一段:
if(900秒内发生了至少一次key的改变){
持久化操作
}else if(300秒至少发生了10次key的改变){
持久化操作
}else if(60秒内发生了至少10000次key的改变){
持久化操作
},这好理解,在我第一天接触Redis时,我记得我set了几个键就去睡觉了,第二天起来发现昨天set的键今天没法get,才想起来应该是没有持久化,然后当天正式学习Redis时,我也没有做过什么手动持久化之类的操作,但是第三天就能get到前一天的值,想必是Redis在900秒内看我发生了一次key的改变,就帮我持久化了。
我将 ./改成了/myredis/目录(使用绝对路径 ),也就是说,下一次持久化就会在此目录下创建dump.rdb,并将数据写入此文件中。
详细说一下:由于我之前都是在root目录下启动的redis服务:
也就是说,root/目录下会有一个dump.rdb 文件保存了我之前set的值,不妨打开来看一看:
在root/下执行 vim dump.rdb
二、AOF
以日志的形式来记录每个操作,将Redis执行过的所有写指令记录下载(读操作不记录),只需追加文件而不能改写文件(这与RDB的覆盖式是不同的),Redis启动之初会读取该文件重新把所有被记录的指令执行一遍,以达到恢复数据的目的,但是时间长了,日志会越来越大。
AOF默认不开启,需要手动在配置文件中配置:
前面提到AOF采用文件追加的方式,为避免出现文件会越来越大的情况,新增了重写机制,当AOF文件的大小超过锁设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用指令bgrewriteaof。
重写虽然可以节约磁盘空间,减少恢复时间,但是每次重写会给CPU造成负担,因此设定的Redis要满足一定条件才会进行重写:系统载入AOF文件或者上次重写完成后,Redis会记录冲刺额后的AOF记录文件的大小,保存在base_size中,如果Redis的AOF在使用过程中的大小>=base_size + base_size*100%,并且当前大小>=64mb时,Redis会对AOF文件进行重写。
完成配置文件得设置以后,来测试一下:
因此当你一不小心将数据flushall以后,可以使用AOF文件来恢复,但有个细节需要注意一下:你的flushall指令也被记录在了此文件中,因此你需要打开此文件手动删除flushall指令并保存。
现在AOF也有了,RDB也有了,那么重启时以谁为准呢?---当AOF和RDB同时开启,系统默认取AOF的数据
AOF故障恢复:
redis-check-aof --fix appendonly,aof
测试:在AOF文件中乱敲一堆数据,这会造成Redis无法启动
shutdown Redis服务,再次重启时发现无法启动,
简述AOF的优点:
备份机制跟稳健,丢失数据概率更低。
可读的日志文件,通过操作AOF,可以处理很多误操作
缺点:
比起RDB占用更多的磁盘空间
恢复备份速度要慢
因为每次写操作或者每秒的写操作要同步到AOF中,会造成一定的性能损耗
存在个别bug,导致不能恢复
三、RDB和AOF的取舍
建议两个都开启。如果对数据不明感,允许少量数据丢失的话,可以只是用RDB,另外,由于AOF存在bug,所以不建议单独使用AOF。如果只是用Redis做关系型数据库的高速缓存,不需要持久化数据,两者都可以不用,毕竟做了任务多了开销。