【redis-02】深入理解redis中RBD和AOF的持久化

news/2024/11/17 0:52:57/

redis系列整体栏目


内容链接地址
【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325
【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756

如需转载,请输入:https://blog.csdn.net/zhenghuishengq/article/details/142441756

redis的持久化机制和原理

  • 一,redis的持久化机制和原理
    • 1,RDB持久化
      • 1.1,save方式实现
      • 1.2,bgsave的实现
      • 1.3,rdb的优缺点
    • 2,AOF持久化
      • 2.1,aof原生命令
      • 2.2,aof重写
    • 3,rdbaof优缺点
    • 4,rdbaof混合持久化

redis_10">一,redis的持久化机制和原理

在平常开发中,redis一般是做为缓存使用,但是在很多大型互联网公司中,都是很依赖redis,将数据存储在redis中,如果redis挂了,那么在重启之后内部的数据就会丢失,因此在redis层面,需要对内部的数据进行持久化。在redis持久化中,主要有两种方式:rdbaof

1,RDB持久化

1.1,save方式实现

redis中,默认使用的就是rdb这种持久化方式,可以通过redis中安装的redis.conf配置文件查看。redis配置的策略如下,可以通过配置save命令来实现持久化的的操作,在一定的时间段,配置一定的阈值,当触发到阈值时,将内存中的数据进行持久化。

save 900 1     # 在 900 秒内至少有 1 次写操作,进行快照
save 300 10    # 在 300 秒内至少有 10 次写操作,进行快照
save 60 10000  # 在 60 秒内至少有 10000 次写操作,进行快照

接下来通过详细案例测试一下,为了测试这个快照,我这边先修改一下配置,在一分钟内,只要有一次写入,那么就会触发这个快照机制

save 60 1  # 在 60 秒内至少有 1 次写操作,进行快照
CONFIG SET save "60 1" //直接在客户端里面操作,和上面这种方式2选1    

随后先清空原有的dump.rdb文件,此时redis中的rdb文件被清空,或者为了测试的话,可以直接先清空所有的key-value,通过 FLUSHALL 命令即可,但是如果是线上环境需谨慎操作

truncate -s 0 dump.rbd

在这里插入图片描述

随后执行几条插入操作的命令,插入完之后,最后在执行以下save命令。在执行命令如果报错error的话,那是因为没满足阈值触发的条件,最好和我一样,改成60s有一次写入就触发存储的机制

set zhenghuisheng:age 18
set zhenghuisheng:height 18
set zhenghuisheng:sex 18    

在这里插入图片描述

随后可以直接查看这个dumo.rdb文件,可以发现数据已经全部存进rdb文件中

在这里插入图片描述

通过数据可以得知,rdb文件是一种二进制文件,更加的适配与操作系统,如果宕机了想要数据恢复的话,那么使用这种二进制文件恢复肯定是效率最高的。

但是如果是使用这种save的方式进行持久化,也会带来部分性能问题,因为save这种方式是采用的 同步 的方式进行数据存储,安全性高,但是如果来了一个 大key,就是一个大对象,如果存一个大对象就要5s,那么此时整个redis都会被阻塞5s,跟内部的反应堆模式有关,那么就会严重影响redis的性能

1.2,bgsave的实现

既然上面的save会由于同步带来一些性能的问题,因此redis也给出了另一份解决思路,就是通过bgsave异步的方式来实现这个rdb快照,从而提高整体的性能的吞吐量。bgsave,即background,后台存储的意思

接下来依旧先演示一下bgsave的使用,先执行三条插入数据的命令,随后执行 bgsave 进行数据存储

set bgsave:001 test1
set bgsave:002 test2
set bgsave:003 test3

在这里插入图片描述

结果如下图,此时三条命令也已二进制的方式存入到dump.db的配置文件中

在这里插入图片描述

bgsave通过 写时复制(copy-on-write) 的方式实现异步操作,就是执行bgsave的主线程,在执行bgsave命令的那一刻,会fork出一个子线程来copy主线程中的所有数据,并且此时如果还有数据写入进来,会同时操作原主线程中的内存数据和新fork出现的子线程中的数据。

既然是使用异步的方式进行数据的持久化,那么就有可能会不安全,数据丢失等问题。

rdb_87">1.3,rdb的优缺点

优点

使用rdb的优点在于,内部采用的是二进制的方式进行数据存储,存储效率较高,如果宕机了要进行数据恢复的话,那么数据恢复也相对较快

缺点

缺点也很明显,首先就是选择存储的方式,即save和bgsave的方式,就是经典的高性能和高可用之间做选择。采用save方式可用保证高可用,数据相对安全,但是可能会出现整个系统出现阻塞问题;采用bgsave方式,通过写时复制的异步方式进行数据的存储,性能相对较快,但是可能造成数据丢失等不安全问题。

还有一个主要的问题,rdb是通过某种阈值触发的条件实现rdb存储,假设5分钟达到1000条命令存储一次,那么如果在这5分钟内的数据刚好到达了阈值临界点,但是此时redis宕机了,导致这5分钟的数据没有进行rbd的持久化,那么就可能会丢失5分钟的数据,在重启redis进行数据恢复的时候,这5分钟的数据将不能恢复

2,AOF持久化

虽然说在redis中默认的是使用rdb这种方式进行持久化,但是rdb这种方式很明显,可能会造成数据丢失比较多的情况,比如一个1w qps/s的系统,假设丢5分钟数据,那么就会丢失掉300万条数据,显然使用默认的方式是不太合理的

100000 * 60 * 5 = 300 0000

aof_109">2.1,aof原生命令

因此redis引入了aof文件日志写入的这种操作,在redis.conf配置文件中,打开 appendonly 设置为yes即可

appendonly yes
CONFIG SET appendonly yes  //直接在客户端中操作,和上面这种方式的效果一样    

在开启完aof命令之后,接下来再往redis中插入几条数据

set aof:test1 aof1
set aof:test2 aof2
set aof:test3 aof3

在这里插入图片描述

数据插入完成之后,接下来查看这个appendonly.aof文件里面到底存的是什么,由于前期aof一直是开着,因此这里只看后面几条命令即可,如果直接cat把数据直接全部的加载到内存里面,把内存撑爆,导致线上的redis服务器宕机了,那就得不偿失了

//查看尾部几条命令
tail -f appendonly.aof

在这里插入图片描述

可以发现里面就是一些原生执行命令。然后加一些redis内部的一些识别符,在数据进行恢复的时候,可以供内部的c++程序所识别,从而实现数据的恢复。实现数据恢复也比较简单,就是把这些命令从上往下的全部的执行一遍,然后就能将数据恢复。

aof持久化也有对应的策略,其持久化的方式有以下三种,默认采用 appendfsync everysec 每秒同步一次数据

  • appendfsync always:每次写入操作都会立即将数据同步到磁盘。安全性最高,但性能最低。
  • appendfsync everysec:每秒同步一次数据,这是默认选项,性能和安全性之间的折中。
  • appendfsync no:由操作系统决定何时同步数据,这样性能最好,但在崩溃时可能丢失一些数据。

到这里为止,丢失问题的情况依旧存在,比如将1s内的数据再提交到对应的日志文件的时候,rdis宕机了,这就会导致可能丢失1秒钟的数据,相对于上面的rdb,已经属于是优化的操作。

但是aof也有属于自己的缺点,rdb采用的是二进制的压缩文件,文件大小相对较小,在做数据拷贝或者恢复的时候相对较快;而aof都是记录原生的命令,包括记录一些字符串长度等等,随着数据的增加,aof文件会越来越大,一次其数据拷贝或者做数据恢复会相对缓慢

aof_151">2.2,aof重写

上面谈到了aof的缺点,会随着时间的推移,文件变得很大,甚至可能不小心一个cat命令,直接把服务器的内存打满,导致redis宕机这种可能,因此aof内部添加了aof重写功能。

举个例子,假设一个减库存的操作,假设商品id为1001,数量有10000件,那么预扣减内存的命令就如下

set 1001:stock 9999
set 1001:stock 9998
set 1001:stock 9997    

就是很明显,这个key不变,但是value在变,如果用aof存的话,可能要存10000条数据,那么aof重写的机制就是,只记录最终值。比如商品卖了5000件,常规的aof就存了5000条数据,但是通过aof重写优化之后,只存最终结果即可,这样在日志中只需要存一条,最后数据恢复时也只需要恢复这条最终的命令即可,其他的数据对于整个系统来讲都是垃圾数据。

set 1001:stock 5000

aof重写策略如下,如在文件达到32m时触发一次重写,在64m时又触发一次… 依次类推

auto-aof-rewrite-percentage:100% 触发AOF重写时,文件大小相对于上一次重写时的百分比阈值
auto-aof-rewrite-min-size:32m    触发AOF重写时,AOF文件的最小大小  //可以通过命令方式设置
CONFIG SET auto-aof-rewrite-percentage 100
CONFIG SET auto-aof-rewrite-min-size 32mb    

除了上面的设置之外,也可以手动的方式触发aof重写,就是通过执行这个 BGREWRITEAOF命令

BGREWRITEAOF

通过aof重写的方式,减少aof存储文件的大小,从而提高在数据做主从架构或者恢复时的效率

rdbaof_188">3,rdbaof优缺点

通过上面的分析,接下来可以对rdbaof二者之前做一个全面的对比。

rdbaof
实现方式save、bgsave原生方式、aof重写
存储方式二进制压缩存储文本命令存储
宕机恢复恢复速度快恢复速度慢
数据安全安全性较低安全性高,最多丢1s数据
启动优先级低,优先级低高,优先使用
主从同步不使用,同步数据少使用,可以同步更多数据

在实际开发中,也是可以优先的考虑使用aof的方式来设计持久化问题,并且不管是在数据做同步上,还是数据恢复上,aof的优势还是占优,都能获取到更多的数据,从而保证系统的高可用。

rdbaof_203">4,rdbaof混合持久化

redis4.0之后,引入了一个新的持久化方式,就是可以让rdb持久化和aof持久化结合使用。rdb的优点是采用二进制存储,存储内容效,aof的优点是存储的数据量多,数据丢失量少,因此结合二者优点,让rbd和aof混合持久化。

在使用这个混合持久化之前,分别需要开启aof持久化和混合持久化的命令。

# 启用AOF持久化
appendonly yes
# 启用混合持久化
aof-use-rdb-preamble yes

aof的维度来讲,肯定是想减少文件的容量大小,并且恢复速度快点,以rdb的维度来讲,肯定是想多存点数据,因此根据这二者维度,可以在aof文件重写之后,将数据转成二进制的格式存到文件中,通过这种方式,通过aof来解决数据丢失问题,又通过rdb文件格式来减少空间存储,并且能再宕机之后更快的恢复数据。

还是通过上面的库存例子详细的说明一下到底什么是混合持久化,首先是开启aof持久化和混合持久化,其次是开启aof的重写功能

auto-aof-rewrite-percentage:100 触发AOF重写时,文件大小相对于上一次重写时的百分比阈值
auto-aof-rewrite-min-size:32m    触发AOF重写时,AOF文件的最小大小 

随后扣减10次库存,为了演示这个文件中的数据,先将 appendonly.aof 文件先清空

truncate -s 0 appendonly.aof 

在这里插入图片描述

随后执行10条扣减库存的操作,如下图,每次对库存进行减1的操作

在这里插入图片描述

执行完成之后,由于此时并没有触发到aof的重写机制,因此需要手动命令进行触发

BGREWRITEAOF

在这里插入图片描述

最后直接查看这个 appendonly.aof 文件,可以发现有部分的二进制文件,有部分的原生命令文件。

就是说那1s的数据会通过rdb的二进制文件进行持久化,在持久化的时候依旧有命令进来,那么暂时先用aof文件进行存储,在下一秒又将前一秒的数据转换成二进制文件存储,通过这种方式最多也只会丢一秒的数据。


http://www.ppmy.cn/news/1530806.html

相关文章

K8S精进之路-控制器StatefulSet有状态控制 -(2)

状态说明 在进行StatefulSet部署之前,我们首先可能要了解一下,什么是"有状态应用"和"无状态应用"。无状态应用就是pod无论部署在哪里,在哪台服务器上提供服务,都是一样的结果,比如经常用的nginx。…

提升工作效率,引领编程新时代

---  随着科技的发展,我们的工作环境也日益复杂,面对的工作压力也越来越大。为了适应这种快节奏的工作环境,选择合适的编程工具成为了提升工作效率的关键。那么,哪款编程工具能让你的工作效率翻倍呢?本文将探讨智能的…

架构师论文备考-论特定领域软件架构

摘要 在2022年3月,我加入了公司新智慧公交平台系统的研发团队,担任架构师一职。我参与了系统整体架构的讨论与设计,并在软件设计方面,指导了调度模块的设计与开发。新智慧公交平台以调度模块为核心,旨在为公交行业调度…

MySQL连接查询解析与性能优化成本

文章目录 一、连接查询1.连接查询基础1. INNER JOIN内连接2. LEFT JOIN (或 LEFT OUTER JOIN)左外连接3. RIGHT JOIN (或 RIGHT OUTER JOIN)右外连接4. FULL OUTER JOIN 2.连接查询的两种过滤条件3.连接的原理 二、性能优化成本1.基于成本的优化2.调节成本常数(1)mysql.server_…

关于公司小程序项目在登录流程获取token并全局使用的梳理(学习篇)

首先打开公司的项目,由于公司前端使用的是tarojsvuebabel,因此需要先安装tarojs-cli并运行编译 之后研究前端前辈们的代码,来学习一下前端怎么获取token并全局使用 首先思路搞清楚,token是通过调取后端的登录接口,并…

接口自动化

一、数据库及数据库操作概念 1.数据库概述 概念 存数据的仓库,程序中数据的载体 数据库和变量都可以存储数据,二者有什么区别? 持久性不同:数据库可以持久性存储数据(将数据写入磁盘文件),而变量不能(运行在内存中) 分类: 关系型数据库(MySQL、Oracle、SQLite):安全 由行和…

前端sm2国密加密时注意

如下方法: export function encrypt(str) {const sm2 require("sm-crypto").sm2;const cipherMode 1; // 1 - C1C3C2,0 - C1C2C3,默认为1//自定义密钥let publicKey "xxxxxxxx";//此处加密let a sm2.doEncrypt(str,…

OpenCV特征检测(8)检测图像中圆形的函数HoughCircles()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在灰度图像中使用霍夫变换查找圆形。 该函数使用霍夫变换的一种修改版本在灰度图像中查找圆形。 例子&#xff1a; #include <opencv2/imgp…