【Redis】浅谈持久化-RDB&AOF
Hi,大家好,我是抢老婆酸奶的小肥仔。
上一篇我们浅谈了下《浅谈Redis的发布(Push)和订阅(sub)》,详情参见:juejin.cn/post/723317…
下面我们来看看redis的持久化。
redis的数据一般保存在内存中,如果在操作过程中突然断电或服务死掉,那么其保存的数据将会丢失,因此我们需要将redis中的数据进行持久化,将其保存到硬盘中。
redis实现数据持久化提供了两种方式:RDB和AOF
1、RDB
RDB即Redis DataBase,即在指定的时间间隔内将内存中的数据集快照写入磁盘(Snapshot快照),恢复时是将快照文件直接读到内存中。RDB持久化后生成的文件的扩展名是.rdb,是一种存储二进制的文件。
1.1 持久化流程
持久化流程图:
1、bgsave通知父线程需要进行RDB备份
2、父进程检查当前redis是否存在正在执行的rdb/aof,如果存在则直接返回,不存在则fork子进程进行rdb持久化。
3、不存在正在执行的rdb/aof,父线程fork出一个子线程进行持久化,该子线程会先将数据写入到一个临时文件中,待持久化过程都结束后,再用这个临时文件替换上次就持久化好的文件。
4、子进程将数据写入新的RDB文件中,并将新的RDB文件替换旧的RDB文件
5、子进程完成RDB快照后,通知父进程关闭子进程(自己理解)
1.2 常用RDB配置
RDB所有的配置都存在于redis.conf中。
dbfilename dump.rdb
:修改rdb备份文件名称,默认:dump.rdb。dir ./
:rdb文件保存的文件目录,默认:./表示执行redis-server命令启动redis时所在的目录。stop-writes-on-bgsave-error
:当磁盘满时,是否关闭redis的写操作。默认:yesrdbcompression
:rdb备份是否开启压缩。默认:yes,采用LZF算法进行压缩,会消耗CPU资源rdbchecksum
:是否检查rdb备份文件的完整性,默认:yes,采用CRC64算法进行数据校验
1.3 触发RDB备份
1.3.1 自动备份
RDB提供了自动备份的触发条件,在redis.conf中配置save就可以了。
语法规则:save 秒钟 写操作次数
默认:1分钟内修改了1万次,或5分钟内需修改了10次,或1小时内修改了1次
表达式:save 60 10000 save 300 100 save 3600 1
1.3.2 手动备份
手动备份有两种触发方式:
save
:save只管保存,不管其他,会导致全部阻塞(父线程也会),手动保存,不建议使用bgsave
:redis异步进行快照操作,即fork出子线程进行备份,而主线程依然可以响应客户端情况。lastsave命令获取最后一次成功生成快照的时间。
1.3.3 flushall命令
执行flushall命令也会产生dump.rdb文件,但是这个rdb文件是空的,无意义。
1.4 RDB备份和恢复
1.4.1 备份
- 通过命令config get dir查找rdb文件的目录
- 将rdb文件拷贝到备份文件加下 cp dump.rdb dump2.rdb
1.4.2 恢复
- 关闭redis
- 先把备份的文件拷贝到工作目录:cp dump2.rdb dump.rdb
- 启动redis,备份数据直接加载,数据恢复
1.5 优缺点
1.5.1 优点
- 适合大规模数据恢复
- 对数据完整性和一致性要求不高更适合使用
- 节约磁盘空间,一般10kb的命令转换成rdb可能只有1kb
- 恢复速度快,不需要像aof一样一个个去执行写命令。
1.5.2 缺点
- fork时,内存数据会被克隆一份,大致2倍
- fork时使用写时拷贝技术,数据量庞大时比较耗性能
- 在一定间隔时间备份一次,如果redis意外down机,会导致最后一次快照数据丢失
2、AOF
AOF(Append Only File):以日志的形式记录每一次写操作,将redis执行过的所有写指令记录下来,只允许追加文件但不可改写文件。数据恢复时,读取AOF的写命令一行行执行来恢复数据。
2.1 持久化流程
- 客户端的请求写命令会被append追加到AOF缓冲区
- AOF缓冲区会根据AOF持久化策略【always/everysec/no】将操作sync同步到磁盘的AOF文件
- AOF文件大小超过重写策略或手动重写时,会对AOF文件进行重写(rewrite),压缩AOF文件容量
- redis服务器重启时,重新load加载AOF文件中的写操作达到数据恢复的目的。
2.2 AOF配置
appendony no
:是否开启AOF,yes:开启,no:关闭。默认:noappendfilename "appendonly.aof"
:aof文件名称,默认:appendonly.aofdir ./
:aof文件所在目录,默认:./,表示执行启动命令时所在的目录,no-appendfsync-on-rewrite
:重写时,不会执行appendfsync操作,该参数表示在正在进行AOF重写时不会将AOF缓冲区的数据同步到旧的AOF文件磁盘。
如果为yes:不写入aof文件,只写入缓存,用户请求不会阻塞,如果宕机,那么这段时间内的缓存数据会丢失(降低数据安全性,提高性能)。
如果为no:数据写入磁盘中,遇到重写时,可能会造成阻塞(数据安全,性能降低)
2.3 AOF和RDB同时开启,redis以谁为准?
redis系统默认取AOF的数据,原因:RDB会丢失最后一次备份的数据,导致数据不完整,而AOF不会存在这种问题,即:AOF的数据完整,不会丢失数据。
2.4 数据恢复
- 正常恢复
1.1 修改默认配置:appendonly no 为 yes
1.2 将备份数据aof拷贝到对应目录(config get fir)
1.3 重启redis服务
- 异常恢复
2.1 修改默认配置:appendonly no 为 yes
2.2 如aof文件损坏:通过/usr/local/bin/redis-check-aof --fix appendonly.aof进行修复
2.2 将备份数据aof拷贝到对应目录(config get fir)
2.3 重启redis服务
2.5 AOF同步频率
redis将写操作追加到aof文件中,多久执行一次追加,redis提供了appendfsync进行设置:
appendfsync always
:每次写入立即同步,这样会导致redis的吞吐量大大降低,违背了redis设计初衷,不推荐使用。
appendfsync everysec
:每秒同步,每秒记录日志一次,如果宕机,也只会丢失1s的数据,更新的命令会放在AOF的缓冲区,每秒在从缓冲区将命令追加到AOF文件,redis默认采用的同步频率。
appendfsync no
:不主动同步,即同步交由操作系统,操作系统同步的周期不固定,最长会有30s间隔,这样出现故障时丢失数据较多。
2.6 AOF文件重写
Redis AOF文件重写是把Redis进程内的数据转化成写命令同步到新AOF文件的过程,重写之后的AOF文件会比旧的AOF文件占更小体积,原因:
- 进程内已超时的数据不在写入文件
- 旧的aof文件含有无效命令,而重写后aof文件只保留最终数据的写入命令
- 多条写命令合并成一条命令,例如: lpush list a、lpush list b、lpush list c可以转化为:lpush list a b c
重写后的aof占用更小的空间,节约了磁盘空间,恢复数据时,aof加载时间更短。
AOF重写分【手动触发】和【自动触发】
2.6.1 重写流程
手动触发:即执行命令:bgrewirteaof
自动触发:在redis.conf修改配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
auto-aof-rewrite-percentage
:表示当前aof文件空间(aof_current_size)和上一次重写AOF文件空间(aof_base_size)的比值,默认100%。
auto-aof-rewrite-min-size
:表示运行AOF重写时AOF文件最小体积,默认:64MB,即AOF文件最小为64MB才有可能触发重写。
流程:
- 手动执行bgrewriteaof命令或自动触发重写,判断当前是否有bgfsave或bgrewriteaof在运行,如果有,则等待命令结束后再继续执行。
- 主进程fork出子线程进行重写操作,保证主进程不会阻塞
- 子进程遍历redis内的数据到临时文件,客户端写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整性以及新AOF文件生成期间的新的数据写操作不会丢失
- 子进程写完新的AOF后,向主进程发送信号,父进程更新统计信息
- 主进程把aof_rewrite_buf中的数据写入新的AOF文件
- 使用新的AOF文件替换旧的AOF文件,完成AOF重写
2.7 优缺点
2.7.1 优点
- 备份机制更全面,丢失数据概率更低
- 可读的日志文件,通过操作AOF文件,可以处理误操作
2.7.2 缺点
- 比RDB占用更多的磁盘空间
- 恢复速度较慢
- 每次写操作同步的话,会造成一定性能压力
- 存在个别bug时,造成不能恢复
转载自:https://juejin.cn/post/7234505799454867516