redis-持久化

RDB

redis dbtabase:在指定时间间隔内,将内存中的数据写入磁盘,相当于一个snapshot快照。恢复时将快照读入内存

工作原理:

  1. 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
2
3
4
保存	时间 操作数
save 900 1
save 300 10
save 60 10000
  1. 在一定时间内操作数达到规定值后,会触发数据备份
  2. 在提交实务后也会触发同步,例如flushall,save等

禁用RDB:

在客户端查看配置:config get save

设置禁用:在配置文件中将save指令注释掉,同时将save ""去掉注释

优势:

  1. 数据备份是fork出来的新进程,io与主进程无关,提高了稳定性
  2. 数据恢复速度快,重新将dump文件读入内存即可

劣势:

  1. 数据备份fork出了一个子进程,内存占用会增加一倍
  2. 按照备份策略,并不是所有的数据都备份到了,在出现意外时,最后一段时间的数据可能没有备份

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
2
3
4
5
appendfsync always	# 实时同步,没必要

appendfsync everysec # 默认,首选

appendfsync no # 不同步,不选

AOF文件的重写

AOF文件会越来越大,达到配置的值时会触发重写。清空之前的AOF文件

1
2
auto-aof-rewrite-percentage 100	# 默认为上次重写时的一倍大小时
auto-aof-rewrite-min-size 64mb # 默认最小为64M,业务比较大时,会设置为几个G

优势

数据完整性好

内存消耗少

劣势

  1. 文件大小大于dump.rdb

  2. 恢复速度慢于RDB

  3. 重启恢复时会有大量的指令执行,占用内存以及大量io操作(触发RDB)

总结

建议两种都开启