当前位置: 首页 > news >正文

Redis 的持久化

9、Redis 的持久化方式

9.1、总体介绍

Redis 是一个基于内存的数据库,它的数据是存放在内存中,内存有个问题就是关闭服务或者断电会丢失。

Redis 的数据也支持写到硬盘中,这个过程就叫做持久化。

Redis提供了2种不同形式的持久化方式:

  • RDB(Redis DataBase)

  • AOP(Append Of File)

9.2、RDB 持久化(Redis Database)

9.2.1、RDB 是什么?

在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的 Snapshot 快照,它恢复时是键快照文件直接读到内存里。

9.2.2、备份是如何执行的

Redis 会单独创建(fork)一个子进程进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束后,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何 IO 操作的,这就是确保了极高的性能,如果需要进行大规模的恢复,且对数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。RDB 的缺点是最后一次持久化后的数据可能丢失。因为如果子进程在写临时文件时,没来得及将临时文件替换上传持久化好的文件,那么这次备份的数据就会丢失。

9.2.3、Fork

  • Fork 的作用是复制一个与当前进程一样的进程,新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,它是一个全新的进程,并作为原进程的子进程;
  • 在 Linux 程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会 exec 系统调用,处于效率考虑,Linux 中引入了“写时复制技术”;
  • 一般情况父进程和子进程会共用一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程;
  • 所以 RBD 方式虽然不影响主进程的 IO 效率,但是降低内存的使用效率,在备份时内存消耗是原来的两倍;

9.2.4、RDB 的持久化流程

在这里插入图片描述

9.2.5、指定备份文件的名称及路径

在 redis.conf 中,rdb 文件的保存的目录是可以修改的,默认为 Redis 启动命令所在的目录,如下

在这里插入图片描述

在 redis.conf 中,rdb 文件的保存的目录是可以修改的,默认为 Redis 启动命令所在的目录,如下

在这里插入图片描述

9.2.6、如何让 Redis 开始备份

方式一:自动备份,需要在配置文件中配置;

在这里插入图片描述

方式二:手动执行备份命令(save/bgsave)

  • save:save 时只管保存,其他不管,全部阻塞,手动保存,不建议使用。
  • bgsave:redis 会在后台异步进行快照操作,快照同时还可以响应客户端情况。
  • 可以通过 lastsave 命令获取最后一次成功生成快照的时间。

方式三:flushall 命令

执行 flushall 命令,也会产生 dump.rdb 文件,但里面是空的,无意义。

9.2.7、redis.conf 中关于 RDB 的相关配置

  1. stop-writes-on-bgsave-error:当磁盘满时,是否关闭 redis 的写操作

    stop-writes-on-bgsave-error 用来指定当 redis 无法写入磁盘的话,是否直接关掉 redis 的写操作, 推荐 yes。

  2. rdbcompression:rdb备份是否开启压缩

    对于存储到磁盘中的 rdb 快照文件,可以设置是否进行压缩,如果是的话,redis 会采用 LZF 算法进行压缩。
    如果你不想消耗 CPU 来进行压缩的话,可以设置为关闭此功能,推荐 yes。

  3. rdbchecksum:是否检查rdb备份文件的完整性

    存储快照后,还可以让 redis 使用 CRC64 算法来进行数据校验,但是这样做会增加大约 10% 的性能消耗,如果希望获取最大的性能提升,可以关闭此功能,推荐yes。

9.2.8、RDB 的备份和恢复

  • 备份:找到 redis.conf 中配置的 RDB 文件,使用 cp 命令,将其拷贝到其他目录,即可备份;
  • 恢复:将备份的 RDB 文件复制到 redis.conf 中配置的目录下,并将其名称改为 redis.conf 中指定的文件名,Redis 在启动时会自动加载 RDB 文件恢复数据;

9.2.9、优势和劣势

优势:

  • 适合大规模的备份数据;
  • 对于数据的完整性要求不高时,推荐使用;
  • 节省磁盘空间;
  • 恢复速度快;

劣势:

  • Fork 的时候,内存中的数据会被克隆一份,内存消耗会翻倍;
  • 虽然 Redis 在 fork 的时候使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能
  • 在备份周期在一定间隔时间做一次备份,所以如果 Redis 意外 down 的话,就会丢失最后一次快照后所有修改;

9.2.10、动态停止 RDB

redis-cli config set save ""	# save 后给空值,表示禁用保存策略。

9.3、AOF 持久化(Append Of File)

9.3.1、AOF 是什么

以日志的形式来记录每个写操作(增量保存),将 redis 执行过的所有写指令记录下来(读操作不记录),只允追加文件但不可改写文件,redis 启动之初会读取该文件重新构造数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

9.3.2、AOF 持久化流程

  • 客户端的请求写命令会被 append 追加到 AOF 缓冲区内;
  • AOF 缓冲区会根据 AOF 持久化策略[always,everysec,no]将操作 sync 同步到磁盘的 AOF 文件中;
  • AOF 文件大小超过重写策略或手动重写时,会对 AOF 文件进行重写(rewrite),压缩 AOF 文件容量;
  • redis 服 务器重启时,会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的;
    在这里插入图片描述

9.3.3、AOF 默认不开启

可以在 redis.conf 文件中对 AOF 配置;

appendonly no	# 是否开启 AOF,yes:开启,no:不开启,默认为 no
appendfilename "appendonly.aof" 	# aof 文件名称,默认为 appendonly.aof
dir ./  # aof 文件所在目录,默认./,表示执行启动命令时所在的目录,比如我们在/opt目录中,去执行 redis-server /etc/redis.conf 来启动redis,那么dir此时就是/opt目录

9.3.4、AOF 和 RDB 同时开启,Redis 听谁的?

AOF 和 RDB 同时开启,系统默认取AOF的数据(数据不会存在丢失,最安全)

9.3.5、AOF 恢复

正常恢复:和 RDB 一样,将 aof 文件放在 redis.conf 配置的路径下即可,启动 Redis 即可;

异常修复:aof 文件损坏,可以通过 /usr/local/bin/redis-check-aof --fix appendonly.aof 进行恢复;

9.3.6、AOF 同步频率设置

在这里插入图片描述

  • appendfsync always:每次写入立即同步
    始终同步,每次redis的写入都会立刻记入日志;性能较差但数据完整性比较好。
  • appendfsync everysec:每秒同步
    每秒同步,每秒记录日志一次,如果宕机,本秒数据可能丢失;更新的命令会放在内存中AOF缓冲区, 每秒将缓冲区的命令追加到AOF文件
  • appendfsync no:不主动同步
    redis不主动进行同步,把同步交给操作系统。

9.3.7、rewrite 压缩(AOF 文件压缩)

rewrite压缩是什么?

AOF 采用文件追加方式,文件会越来越大,为了避免出现此情况,新增了重写机制,当 AOF 文件的大小超过锁审定的阈值时,Redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令 bgrewriteaof 触发重写。

重写原理,如何实现重写?

AOF文件持续增长而过大时,会 fork 出一条新进程来将文件重写(也是先写临时文件,最后在 rename 替换旧文件),redis4.0 版本后的重写,是指就把rdb 的快照,以二进制的形式附在新的aof头部,作为已有的历史数据,替换掉原来的流水账操作。

触发机制,何时重写?

  • bgrewriteaof:手动触发重写

    从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, bgrewriteaof 仅仅用于手动触发重写操作。

    redis 会记录上次重写的 aof 大小,默认配置是当 aof 文件大小是上次 rewrite 后大小的 2 倍且文件大于 64M 时触发。
    重写虽然可以节约大量磁盘空间,减少恢复时间,但是每次重写还是有一定负担的,因此设置 redis满 足一定条件才会进行重新。

  • auto-aof-rewrite-percentage:设置重写基准值

    设置重写的基准值,默认 100,当文件达到 100% 时开始重写(即文件是原来重写后文件的 2 倍时重写);

  • auto-aof-rewrite-min-size:设置重写基准值

    设置重写的基准值,默认 64MB,AOF 文件大小超过这个值开始重写。

示例

文件达到70MB开始重写,降到50MB,下次什么时候开始重写?100MB

系统载入时或者上次重写完毕时,redis 会记录此时 AOF 大小,设置 base_size。

如果 Redis 的 AOF 当前大小 >= base_size + base_size * 100% (auto-aof-rewrite-percentage默认值)且当前大小 >= 64mb(auto-aof-rewrite-min-size默认值)的情况下,redis 会对 AOF 进行重写。

重写流程

  1. 手动执行 bgrewriteaof 命令触发重写,判断是否当前有 bgfsave 或 bgrewriteaof 在运行。如果有,则等待该命令结束后再继续执行;
  2. 主进程 fork 出子进程执行重写操作,保证主进程不会阻塞;
  3. 子进程遍历redis内存中的数据到临时文件,客户端的写请求同时写入 aof_buf 缓冲区和 aof_rewrite_buf 重写缓冲区保证原 AOF 文件完整性以及新 AOF 文件生成期间的新的数据修改动作不会丢失;
  4. 子进程写完新的AOF文件后,向主进程发送信号,父进程更新统计信息;
  5. 主进程把 aof_rewrite_buf 中的数据写入到新的 AOF 文件;
  6. 使用新的 AOF 文件覆盖旧的 AOF 文件,完成 AOF 重写;

在这里插入图片描述

no-appendfsync-on-rewrite:重写时,不会执行 appendfsync 操作

  • 该参数表示在正在进行 AOF 重写时不会将 AOF 缓冲区中的数据同步到旧的 AOF 文件磁盘,也就是说在进行 AOF 重写的时候,如果此时有写操作进来,此时写操作的命令会放在 aof_buf 缓存中(内存中),而不会将其追加到旧的 AOF 文件中,这么做是为了避免同时写旧的 AOF 文件和新的 AOF 文件对磁盘产生的压力。
  • 默认是 ON,表示关闭,即在 AOF 重写时,会对 AOF 缓冲区中的数据做同步磁盘操作,这在很大程度上保证了数据的安全性。
  • 但在数据量很大的场景,因为两者都会消耗磁盘 IO,对磁盘的影响较大,可以将其设置为“yes”减轻磁盘压力,但在极端情况下可能丢失整个 AOF 重写期间的数据。
  • 如果 no-appendfsync-on-rewrite 为 yes,不写入 aof 文件,只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。(降低数据安全性,提高性能)(如果将 no-appendfsync-on-rewrite 设置为 yes,即在 AOF 重写时不会将 Redis 的写操作写入旧 AOF 文件中。如果在重写期间,Redis 意外宕机,那么 AOF 重写期间的所有写操作都没有记入旧 AOF 文件,Redis 再通过 AOF 恢复数据时,就会丢失重写期间的所有写操作);
  • 如果 no-appendfsync-on-rewrite 为 no,还是会把数据库往磁盘里刷,但是遇到重写操作,可能会发生阻塞。(数据安全,但是性能降低)

9.3.8、AOF 的优势与劣势

优势:

  • 数据安全性更高,丢失数据概率更低
  • 可读的日志文本,通过操作 AOF 文件,可以处理误操作

劣势:

  • 比 RDB 占用更多的磁盘空间
  • 恢复备份速度要慢
  • 每次读写都同步的话,有一定的性能压力
  • 存在个别 bug,造成不能恢复

9.3.9、总结

  • AOF 文件是一个只进行追加的日志文件
  • Redis 可以在AOF文件体积变得过大时,自动地在后台对 AOF 文件进行重写
  • AOF 文件有序地保存了对数据库执行的所有写入操作,这些写入操作以 redis 协议的格式保存,因此 AOF 文件的内容非常容易被人读懂,对文件进行分析也很轻松。
  • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积
  • 根据所使用的 appendfsync策略,AOF 的速度可能会慢于 RDB

9.4、用哪个好?

  • 官方推荐 2 个都启用。
  • 如果对数据不敏感,可以单独用 RDB。
  • 不建议单独使用 AOF,因为可能会出现 BUG。
  • 如果只是做纯内存缓存,可以都不用。

9.6、官网建议

  • RDB 持久化方式能够在指定的时间间隔对你的数据进行快照存储;
  • AOP 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始数据,AOF 命令以 redis 协议追加保存每次写的操作到 AOF 文件末尾;
  • Redis 还能对 AOF 文件进行后台重写,使得 AOF 文件的体积不至于过大;
  • 只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式;
  • 同时开启两种持久化方式;
    • 在这种情况下,当 redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整,即相对于数据安全性,AOF 比 RDB 更安全;
    • RDB 的数据不实时,同时使用两者时服务器重启也只会找 AOF 文件,那如果只是用 AOF 呢?
    • 建议不要,因为 RDB 更适合用于备份数据库(AOF在不断变化不好北非),快速重启,而且不会有 AOF 可能潜在的 bug,留着作为一个万一的手段;
  • 性能建议
    • 因为RDB文件只用作后备用途,建议只在 Slave 上持久化 RDB 文件,而且只要 15 分钟备份一次就够了,只保留 save 900 1 这一条;
    • 如果使用 AOF,好处是在最恶劣的情况下也只会丢失不超过两秒数据,启动脚本较简单只 load 自己的 AOF 文件就可以了;
    • AOF的代价,一是带来持续的 IO,二是 AOF rewrite 的最后将 rewrite 过程中产生的新数据 (aof_rewrite_buf)写到文件造成的阻塞几乎是不可避免的;
    • 只要硬盘许可,应该尽量减少 AOF rewrite 的频率,AOF 重写的基数大小默认值 64M(auto-aof-rewrite-min-size)太小了,可以设置到 5G 以上
      默认超过原大小 100%(auto-aof-rewrite-percentage)大小时重写可以改到适当的数值;

相关文章:

  • 2022年中国证券行业智能投顾专题分析
  • MYSQL高可用架构之MHA实战(真实可用)
  • 【Reinforcement Learning】蒙特卡洛算法
  • SAP ABAP ADT安装说明 as 20220901
  • 计算机组成原理知识总结(八)输入/输出系统
  • springboot基于java的康泰小区物业管理系统的设计与实现毕业设计源码101926
  • java查看对象真实地址和哈希值的工具类
  • SOLIDWORKS直播课:解锁3DE协同设计平台的“云端结构设计角色”
  • 简单的 手写 服务器
  • 01 RocketMQ - NameServer 源码分析
  • 【CSS】数据面板
  • 记一次盖茨木马应急响应
  • 兔老大的系统设计(二)定时系统(延时队列)
  • STM32cubeMX详细教学及多个小项目合集(包含RTOS)
  • 车联网白皮书(2021.12)中国信息通信研究院
  • hexo+github搭建个人博客
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • IndexedDB
  • JavaScript HTML DOM
  • Java应用性能调优
  • MYSQL 的 IF 函数
  • Redis在Web项目中的应用与实践
  • Sass 快速入门教程
  • vue-loader 源码解析系列之 selector
  • 多线程 start 和 run 方法到底有什么区别?
  • 关于List、List?、ListObject的区别
  • 后端_ThinkPHP5
  • 前端技术周刊 2019-02-11 Serverless
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 入门级的git使用指北
  • 世界上最简单的无等待算法(getAndIncrement)
  • 微信小程序填坑清单
  • 鱼骨图 - 如何绘制?
  • scrapy中间件源码分析及常用中间件大全
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (十八)三元表达式和列表解析
  • (十六)Flask之蓝图
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • .aanva
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .net core 6 redis操作类
  • .NET 设计一套高性能的弱事件机制
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [BPU部署教程] 教你搞定YOLOV5部署 (版本: 6.2)
  • [BZOJ 1040] 骑士
  • [Design Pattern] 工厂方法模式
  • [dfs搜索寻找矩阵中最长递减序列]魔法森林的秘密路径
  • [Grafana]ES数据源Alert告警发送