首先要了解为什么要持久化:由于Redis是内存数据库,宕机后数据会丢失,所以需要提供持久化机制,以便重启后快速恢复数据。持久化的目的是为了快速恢复数据而不是为了存储数据。这个思想很重要,因为是否允许丢失数据,和是否允许丢失多少数据,直接决定了Redis的部分性能。
持久化方案有以下3种
- 1、RDB (Redis DataBase)
- 2、AOF (Append Only File)
-
RDB
RDB是一个紧凑的二进制文件,是某个时刻完整的数据快照,只关注数据结果,而不关注数据过程。
快照触发方式 1、符合自定义配置的快照规则
save "" # 不使用RDB存储 不能主从
save 900 1 # 表示15分钟(900秒钟)内至少1个键被更改则进行快照。
save 300 10 # 表示5分钟(300秒)内至少10个键被更改则进行快照。
save 60 10000 # 表示1分钟内至少10000个键被更改则进行快照。
2、执行save或者bgsave命令
- save:阻塞主进程,此时Redis不可用。等save结束后才可用。
- bgsave:fork子进程进行save操作,fork过程是阻塞的,Redis不可用。save结束后,通知主进程,子进程关闭。
- 3、执行flushall命令(清空数据库中的所有key)
- 4、执行主从复制(第一次时)
- 5、手动退出Redis服务(shutdown)。shutdown关闭服务前会立即进行持久化,而 kill 服务进程,会根据save配置判断是否需要持久化。
优点
- 1、RDB是二进制压缩文件,存储空间小,便于传输(主从第一次时)。
- 2、持久化时是fork子进程进行操作,对Redis性能影响不大。但需要注意:如果Redis中有比较多数据,在fork时会比较耗时,而且fork是阻塞的,此时Redis不可用。
缺点
-
AOF
AOF默认不开启。开启配置为
appendonly yes
。AOF文件记录的是redis每次执行的命令,恢复操作就是按顺序回放这些命令。
AOF原理
同步命令到AOF的过程分为下面3步: 1、命令传播(接收命令):Redis将执行完的命令发送到AOF程序中
- 2、缓存追加(写缓存):AOF程序将接收到的命令转为网络通讯的格式,并写入AOF缓存中
- 3、文件写入和保存(刷盘):如果设定的条件满足(AOF保存模式),将缓存写入AOF末尾,fsync或fdatasync函数会被调用,此时才是真正写文件。
AOF保存模式
目前支持以下三种:
- AOF_FSYNC_NO:不保存。每次接收到命令都写缓存,但不刷盘。只有在1、Redis被关闭 2、AOF功能被关闭 3、系统的写缓存被刷新(写缓存满或定期刷新)在这3中情况下才会刷盘,刷盘过程中会阻塞Redis。
- AOF_FSYNC_EVERYSEC:每秒保存一次(默认)。每次会fork子进程操作,fork之后Redis不阻塞。
- AOF_FSYNC_ALWAYS:每执行一个命令,保存一次(不推荐)。每条命令都会刷盘,每次都会导致Redis阻塞。
AOF重写
当AOF文件体积变得过大时,会自动fork子进程对AOF进行重写,达到瘦身的目的。
比如:
set aaa 11
set aaa 22
set aaa 33
最终会被优化成 set aaa 33
RDB和AOF结合
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化。如果把混合持久化打开,AOF rewrite 的时候就直接把 rdb 的内容写到 aof 文件开头。
开启配置为aof-use-rdb-preamble yes
RDB AOF比较
- 存储
- RDB:存储数据快照,以二进制形式存储。
- AOF:存储命令,以文本方式存储。
- RDB性能高,AOF性能低
- RDB会丢失最后一次快照之后的数据。AOF根据配置的不同有所区别
- AOF_FSYNC_NO:不保存。会丢失最后一次刷盘后的数据
- AOF_FSYNC_EVERYSEC:每秒保存一次(默认)。一般丢失数据不超过两秒
- AOF_FSYNC_ALWAYS:每执行一个命令,保存一次(不推荐)。丢失最后一个命令的数据
- 关于过期键
- RDB:Redis以主服务器模式运行时,不会保存已经过期的键值对数据。Reids已从服务器模式运行时,RDB会保存过期键值对数据,当主服务器向从服务器同步时,会清空过期键值对数据。
- AOF:AOF写入文件时,会对已过期的key追加一条del命令,执行AOF回放时,会忽略过期key和del命令。
关于还原:同时有RDB和AOF时,优先还原AOF,因为RDB可能会丢更多数据。
RDB AOF如何选择
1、如果需要命令不丢失:使用AOF+RDB
- 2、用作缓存:RDB。因为RDB性能高
- 3、如果有数据源,而且每次启动都从该数据源初始化数据:两者都不开。比如字典库类的缓存。
- 4、如果Redis数据量过大,性能突然下降:只开启AOF。因为RDB会fork子进程进行RDB操作,而fork子进程时会dump主进程的副本,造成fork时间过长,导致Redis阻塞过长时间。