redis-持久化
RDB
redis dbtabase:在指定时间间隔内,将内存中的数据写入磁盘,相当于一个snapshot快照。恢复时将快照读入内存
工作原理:
- fork一个与原进程一样的进程用来进行数据备份(同步、持久化)。由于fork出来的进程的所有数据与原来的一致,所以会出现两个结果:
- 占用内存增加一倍,也就是说开启RDB之后,最大内存限制必须小于实际内存的一半
- 由于数据的备份是通过fork出来的进程,所以不会影响父进程的io操作,确保了redis的稳定高效性
保存文件:
备份的文件为redis.conf中指定的文件名dbfilename dump.rdb
:dump.rdb
保存的路径为redis.conf中指定的路径dir /var/lib/redis
:/var/lib/redis
恢复文件:
在redis重启后,会按照配置文件中给定dir的路径去寻找备份文件dump.rdb,并自动读入内存
备份策略:
1 | 保存 时间 操作数 |
- 在一定时间内操作数达到规定值后,会触发数据备份
- 在提交实务后也会触发同步,例如flushall,save等
禁用RDB:
在客户端查看配置:config get save
设置禁用:在配置文件中将save指令注释掉,同时将save ""
去掉注释
优势:
- 数据备份是fork出来的新进程,io与主进程无关,提高了稳定性
- 数据恢复速度快,重新将dump文件读入内存即可
劣势:
- 数据备份fork出了一个子进程,内存占用会增加一倍
- 按照备份策略,并不是所有的数据都备份到了,在出现意外时,最后一段时间的数据可能没有备份
AOF
append only file,为了弥补RDB无法保证完整备份的缺陷。
思考
如何避免RDB所带来的数据丢失的问题?
因为RDB备份的条件是操作数在规定时间内达到规定值才会触发,总不能通过降低触发条件,毕竟备份也很浪费计算机资源,会增加内存容量负担,cpu压缩文件带来的性能损耗。
数据在内存中,要保存到磁盘中,又不可能实时同步,那样不是会降低计算机性能吗?似乎是一个不可避免的矛盾,我觉得是不是可以采用overlayfs的思想,实现不完全的同步?
不过redis采用了更加高级的思想,并不是眼光局限在数据本身上,而是站在了更高的角度去看待问题。从整个过程去思考。首先是我们发出指令去插入/修改数据,然后数据才被写入内存,最后才有数据同步问题。如果我们将所有指令保存下来,那么就不会出现前面的问题了。由于指令存在重复的,便可以简化。
工作原理
将所有的写指令,不包括读指令写入到一个文件中,在redis重启时会读取这个文件,重新执行一遍命令,恢复所有数据。
启用
默认不启用,启用修改配置为:appendonly yes
保存文件
配置文件中设置:appendfilename "appendonly.aof"
文件位置和dump.rdb的位置一样
恢复
如果同时存在appendonly.aof和dump.rdb,那么会优先读取aof文件。
如果dump.rdb被删掉了,只存在appendonly.aof那么通过systemd来启动会报错,使用redis-server /etc/redis/redis.conf可以成功启动
错误修复
如果由于意外情况aof文件中有一些错误数据也是无法启动的,可以通过命令redis-check-aof
修复
1 | redis-check-aof --fix /etc/redis/appendonly.aof |
同步策略
1 | appendfsync always # 实时同步,没必要 |
AOF文件的重写
AOF文件会越来越大,达到配置的值时会触发重写。清空之前的AOF文件
1 | auto-aof-rewrite-percentage 100 # 默认为上次重写时的一倍大小时 |
优势
数据完整性好
内存消耗少
劣势
文件大小大于dump.rdb
恢复速度慢于RDB
重启恢复时会有大量的指令执行,占用内存以及大量io操作(触发RDB)
总结
建议两种都开启