Redis持久化
为什么需要持久化
其实在我们工作中也有多持久化场景,比如word。它的持久化形式是以~$论文.docx的形式来持久化。
那么在Redis中为了防止数据意外丢失,确保数据安全,也会进行持久化。
利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化。
在Redis中有两种持久化方式:RDB(Redis DataBase)、AOF(Append Only File)。
RDB(Redis DataBase)将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据。
AOF(Append Only File)将数据的操作过程进行保存,日志形式,存储操作过程,存储格式复杂,关注点在命令。
RDB持久化
在Redis中可以使用save命令来执行一次RDB持久化操作.
save指令相关配置:
- dbfilename.dump.rdb
- 说明:设置本地数据库文件名,默认值为dump.rdb
-
- dir
- 说明:设置存储.rdb文件的路径
-
- rdbcompression yes
- 说明:设置存储至本地数据库时是否压缩数据,默认为yes,采用LZF压缩
-
- rdbchecksum yes
- 说明:设置是否进行RDB文件格式校验,该校验在写文件和读文件过程均进行
我们知道早期Redis版本是单线程的。当我们执行save命令时会阻塞当前Redis服务器,直到RDB过程完成为止,有可能会造成长时间阻塞,线上环境不建议使用。
那么问题来了,既然使用save会对线上服务器造成影响,那么有没有一种更好的持久化方式呢?答案是有的,那就是bgsave.
通过名称可以看出这个持久化操作是后台执行的,不会导致Redis发生阻塞。
下面看一下bgsave的工作原理:
可以看出,当执行bgsave命令后Redis会fork出一个子进程,用于创建RDB文件进行持久化,这样一来就不会阻塞Redis了。但是bgsave不会立即执行,且会消耗额外的CPU资源。
bgsave命令是针对save阻塞问题做的优化。Redis内部所有涉及到RDB操作都采用bgsave的方式,save命令可以放弃使用。
bgsave指令相关配置:
- dbfilename.dump.rdb
- 说明:设置本地数据库文件名,默认值为dump.rdb
-
- dir
- 说明:设置存储.rdb文件的路径
-
- rdbcompression yes
- 说明:设置存储至本地数据库时是否压缩数据,默认为yes,采用LZF压缩
-
- rdbchecksum yes
- 说明:设置是否进行RDB文件格式校验,该校验在写文件和读文件过程均进行
-
- stop-writes-on-bgsave-error yes
- 说明:后台存储如果出现错误,是否停止保存操作
那么问题又来了,我们不可能一直手动去执行或者bgsave指令,这时Redis为我们提供了自动执行bgsave的功能。
在Redis的配置文件中有这么一个配置save [secone] [changes]可以帮助我们自动进行持久化。
- 配置:
- save second changes
-
- 作用:
- 满足限定时间范围内key的变化数量达到指定数量即进行持久化
-
- 参数:
- second:监控时间范围
- changes:监控key的变化量
-
- 位置:
- 在conf文件中进行配置
-
- 范例:
- save 900 1
- save 300 10
- save 60 10000
注意: save配置要根据实际业务情况进行设置,频度过高或过低都会出现性能问题,结果可能是灾难性的 save配置中对于second与changes设置通常具有互补对应关系,尽量不要设置成包含性关系 save配置启动后执行的是bgsave操作
RDB三种持久化方式对比:
RDB的优点:
- RDB是一个紧凑的压缩二进制文件,存储效率高
- RDB是内部存储的在Redis某个时间点的数据快照,非常适用于数据备份,全量复制等场景
- RDB恢复数据的速度要比AOF快的多
- 服务器每X个小时执行bgsave备份,并将RDB文件拷贝至远程机器中,用于灾难恢复
RDB的缺点:
- RDB无论是执行指令还是利用配置,都无法做到实时持久化,具有较大的可能性丢失数据
- bgsave每次执行都会fork创建子进程,要牺牲掉一些性能
- Redis众多版本中,没有对RDB文件格式统一,有可能出现各版本数据不兼容的情况
AOF持久化
AOF(Append Only File)持久化,以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。与RDB相比可以简单描述为数据产生的过程。
AOF主要作用是解决了持久化的实时性,目前已经是Redis持久化的主流方式。
AOF持久化过程
在把AOF命令缓冲区同步到文件时有三种写数据策略(appendfsync):
- always(每次)
- 每次写入操作均同步到AOF文件中,数据零误差,但性能较低
-
- everysec(每秒)
- 每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能也较高
- 在系统突然宕机是会丢失1秒内的数据
-
- no(系统控制)
- 由操作系统每次同步到AOF文件的周期,整体过程不可控
Redis开启AOF功能持久化
配置:
- appendonly yes|no
- 作用:是否开启AOF持久化,默认为不开启状态
-
- appendfsync always|everysec|no
- 作用:AOF同步命令数据策略
-
- appendfilename filename
- AOF持久化文件名,默认文件名为appendonly.aof,建议配置成appendonly-端口号.aof
AOF在遇到相同命令是如何处理呢
假如同步策略是 appendfsync everysec每秒同步一次,执行如下命令:
- set name zhangsan
- set name lisi
- set name wangwu
最终AOF文件里将只有一条:
- set name wangwu
AOF重写
随着AOF文件不断写入,AOF文件会越来越大,为了解决这个问题,Redis引入了AOF重写机制压缩文件体积。
AOF文件重写是将Redis进程内的数据转化为写命令同步到新AOF文件的过程。简单说就是将若干条命令执行结果转化成最终结果数据对应的指令进行记录。
AOF 重写的作用
- 降低磁盘占用量,提高磁盘利用率
- 提高持久化效率,降低持久化时间,提高IO性能
- 降低数据恢复的时间,提高数据恢复效率
AOF重写的规则
- 进程内已经超时的命令不再写入文件
- 忽略无效指令,重写时使用进程内数据直接生成,这样新的AOF中只保留最终数据的写入命令
- del key1
- hdel key2
- 对同一数据写命令合并为一条命令
- 如下命令:
- lpush list1 a、lpush list1 b、 lpush list1 c
- 可以转化为:
- lpush list1 a b c。
-
- 为防止数据量过大造成客户端缓冲区溢出,对list、set、hash、zset等类型,每条指令最多写入64个元素
AOF重写规则
- 手动重写
- bgrewriteaof
- 自动重写
- auto-aof-rewrite-min-size size
- auto-aof-rewrite-percentage percentage
AOF重写流程
AOF持久化+重写:
- 执行set等命令
- 主进程先是执行这条命令,紧接着fork一个子进程,用于往AOF缓存区和AOF重写缓存区写命令
- 满足条件后写入AOF文件
- 当bgwriteaof执行时,同样会fork一个子进程从AOF重写缓存区读取指令并重启,同时提示bgwriteaof正在执行
- 重写完成后,替换原来的.aof文件
RDB与AOF的区别
RDB与AOF如何选择
对数据敏感,建议使用默认的AOF持久化方案
- AOF持久化策略使用everysec,每秒钟fsync一次。该策略可以很好的保持处理性能,当出现问题时最多丢失0-1秒钟的数据。
- 注意:由于AOF存储体积较大,所以恢复速度较慢
数据呈现阶段有效性,建议使用RDB持久化方案
- 数据可以良好的做到阶段内无丢失,且恢复速度较快,阶段点数据恢复通常使用RDB方案
- 注意:利用RDB实现紧凑的数据持久化会使Redis性能降低
综合对比
- RDB与AOF的选择实际上是在做一种权衡,每种都有利弊
- 如果不能承受数分钟以内的数据丢失,对业务非常敏感,选用AOF
- 如果能接受数分钟以内的数据丢失,且追求大数据集的回复速度,选用RDB
- 灾难恢复选RDB
- 双保险策略,同时开启RDB与AOF,重启后,Redis优先使用AOF来恢复数据,降低丢失数据的量
持久化应用场景
- 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计
- 应用于具有操作先后顺序的数据控制
- 应用于最新消息展示
- 应用于基于黑名单与白名单设定的服务控制
- 应用于计数器组合排序功能对应的排名