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

初识Redis · 持久化

目录

前言:

RDB

AOF


前言:

本文开始,就已经算是Redis的进阶篇文章啦,因为从本文开始就要开始涉及到了Redis的一些特性和一些底层原理了。

那么首当其冲的,就是Redis中的持久化了,我们提及持久化之前,我们不妨回想一下MySQL中的事务有哪些特性,一共有4个是吧,分别是原子性,一致性,持久性,隔离性。对于MySQL中的持久性,因为MySQL中和硬盘打交道的,也就是说重启了服务器之后,数据依旧是存储在硬盘的,那么数据也就有了持久性的特点。而对于Redis就不同了,它是一共内存级别的数据库,也就是数据都在内存中,那么如何保证数据的持久性呢?

我们在平常使用的时候,其实已经发现了,当我们设置了一些键值对之后,我们退出Redis客户端,再重新登录的时候数据又有了,这其实就得益于Redis的持久化机制。

那么,本文将从两个角度,介绍Redis的持久化操作,这其实就是Redis的持久化机制,分别是RDB和AOF机制。


RDB

首先,我们要明确一个点是,既然要实现持久化操作,那么肯定要和硬盘打交道的,也就是说,Redis同时和内存硬盘打交道,不过代价也非常直观,消耗了更多的空间,不过因为硬盘价格便宜,所以开销的成本也是可以忽略的。

RDB的全名叫做:Redis database

这个操作是定期把数据从内存备份到硬盘里面,生成对应的“快照”,当Redis重启的时候,就可以根据这个快照,恢复内存中的数据了。

那么这个定期恢复的定期来说,一般有两种方式,一种是手动触发,一种是自动触发,对于手动触发来说,涉及到了两个命令,分别是save和bgsave。

对于手动触发

其中对于save来说,一旦执行了这个命令,那么Redis就会全力执行“快照”生成的操作了,那么如果Redis的数据量比较大,就会阻塞其他客户端的命令,这个操作就比较类似于keys *了,所以是不建议使用的。

其中对于bgsave来说,我们光从名字就可以发现,backgroud save,后台保存,它的意思就是Redis会在后台执行备份的这个操作。那么如何实现的呢?难道偷摸引入了一个线程?实际上并不是,Redis不是通过多线程的方式实现的,它使用的是多进程方式。

这个点其实还是比较让人惊讶的,在Redis的单线程玩久了,突然想起来还有一个进程,是吧。

就像是这样的。

对于自动触发

就非常好理解了,Redis会根据对应的配置文件,每m秒数据的吞吐量达到了n,就会进行一次备份,这点,我们是可以在Redis的配置文件里面看到的。

而不管是手动触发还是自动触发,其实都会生成对应的快照文件,这个文件的路径我们也是可以在Redis的配置文件里面看到的。

当我们打开配置文件,在/etc/redis/的redis.conf里面,我们找到这一行,就能发现RDB的快照是存放在Redis的工作目录里面的,所以我们要找对应的快照,就要cd /var/lib/redis里面去看看。

在这里我们确实是发现了,那么我们使用vim打开看看:

我们也能在里面发现一些我们目前有的键值对的身影:比如lisi等。

那么我们清空了之后:

也确实发现了它里面的内容不见了。

这个时候同学就会说了,欸你不是说Redis有手动触发和自动触发吗?这也没看你手动触发啊,是不是因为自动触发了,实则不然,我们可以看看在配置文件里面的自动触发的配置:

配置文件里面有这么一段话,save the DB on disk,也就是说保存数据到硬盘上,它的基本格式是save second changes,也就是说多少秒发生了多少个键值对的改变,就会进行一次生成快照。

在默认的配置文件里面,是有三种规格,一次是15分钟动了一个键值对,一次是5分钟动了十个键值对,一次是一分钟动了10000个键值对

上面的save ""的操作是不自动生成快照

而在我们刚才的操作里面,虽然我们都不满足手动触发和自动触发的条件,但是我们退出客户端重新进入客户端的这个操作,Redis就会默认更新RDB文件了。

那么我们现在可以试试手动触发一下:

不管是save还是bgsave,对应的快照文件我们重新进入都会更新,并且我们也能发现一些我们刚设置的key。

那么这是对应的操作,我们能够发现对于dump.rdb文件来说,它里面的数据都是一些二进制文件,在存储的时候,就会通过压缩内存中的数据,保存到这个二进制文件中。

那么问题来了:

第一个:我们rdb文件是怎么生成的呢?是原地修改的还是重新创建一个再覆盖呢?

第二个:当我们创建一个key,而对应的dump.rdb文件没有及时生成,服务器突然挂了,新创建的key是否存在呢?

首先是第一个问题,对于save来说,这是阻塞式保存,Redis会停止其他服务,原地覆盖rdb文件,对于bgsave来说,采用子进程的方式重新创建,创建成功之后覆盖原来的rdb文件,所以inode会改变。那么问题来了,如果子进程保存快照的时候,父进程仍然在输入数据,恰好父进程突然挂了,那么新的数据就没有了,这个怎么办?

它的解决方法就是使用AOF或者主从复制等了,这个后面细说了。我们现在先来验证bgsave的机制:

 对于第二个问题,我们的操作是创建一个key,然后异常关闭服务器,再连接,这个时候服务器就相当于断电了,那么对应的rdb文件就没有正常生成,所以我们查询不到对应的数据。咱其实日常基本都是正常关闭,但是我们最怕的就是异常关闭,比如kill这种。

而对于rdb文件来说,我们要记住旧版本的rdb文件不一定能被新版本的redis识别

不知道有没有坏心思的同学,既然我们能够随便查看对应的rdb文件,我们是否能够更改呢?

当然是可以的,但是我们要记住一点,rdb文件如果出现损坏,redis服务器可能就起不来了,那么是不是我们只要不动它就不会损坏呢?那不见得,某些操作,比如网络传输都是由可能导致它出错的。

我们现在来恶意损坏试试:

此时我们已经损坏完成,然后我们重启一下redis服务器:

此时我们使用redis-check-rdb程序就可以判断出对应的rdb文件出错了。那么我们的解决方案可以是直接给rdb文件删除了,或者使用之前备份过的。

此时我们的RDB就简单的算完成了,我们可以简单的总结一下。

RDB是服务器通过生成快照的方式进行持久化操作的一种机制,涉及到的命令有save和bgsave,其中save是阻塞式保存,bgsave式后台子进程+覆盖rdb文件的方式保存,涉及到的检查工具有redis-check-rdb,因为redis是内存数据库,所以在服务器没有挂的时候我们直接退出客户端,也不save或bgsave的,也能get到对应的数据,我们复习的时候也能通过这个问题来引入RDB操作。


AOF

那么我们通过对RDB操作的理解,我们发现RDB的方式是用来存储数据来保证数据的持久化的,那么数据怎么来的?数据实际上是我们使用各种操作而来的,那么有没有一种操作是通过保留操作来持久化数据的呢?

对于AOF(Append Only File)来说,它的操作就是通过保留操作来进行持久化的,它就可以解决RDB不能实时保留数据的缺点了,对于AOF来说,它默认是关闭的,当我们开启AOF操作的时候,启动的时候也就不再读取RGB文件了。

我们首先现在配置文件里面把AOF打开并且重启服务器:

并且我们也看到了对应的文件名叫做appendonly.aof,它的位置还是在/var/lib/redis中。

当我们插入了数据之后,也确实看到了里面记录着一些我们的操作。那么现在有一个问题了,Redis既然是一个单线程服务器,写入内存的同时还要兼顾到硬盘的AOF文件,是否会降低它的速度

答案是不会的,因为它并不是说你执行一个命令就往aof文件里面写入,它的操作是存在一个内存缓冲区,积累到一定程度就写入,所以会效率的影响不是很大,并且如果是在硬盘随机读写的话,速度是较慢的,但是好在Redis对AOF文件是末尾写入,也就是顺序写入,所以并不算慢。

对于AOF文件的写入机制主要还是因为这句话:写入硬盘的数据量并不能决定效率,而是写入次数

那么同样还是服务器突然挂掉的情况,AOF如果没有及时写入,也是会丢失对应的操作数据的,这个时候Redis就给出了一些选项,让我们根据情况取舍,在次数和数据量之间进行平衡。

配置项含义说明写入频率数据安全性性能影响适用场景示例
appendfsyncalways每次写命令都立即同步写入 AOF 文件每条命令最安全性能最差对数据极为敏感的金融或订单类系统
appendfsynceverysec(默认)每秒同步一次,可能丢失 1 秒以内的数据每秒一次较高性能较好大多数业务场景,如缓存、常规数据库替代
appendfsyncno仅由操作系统控制何时将数据刷新到磁盘不固定较低(可能丢较多数据)性能最佳数据不重要的缓存场景,或自己手动控制持久化

同样,我们也是能在配置文件里面进行修改。

那么,当我们试想一下,如果我们set了一个key,又del了,我们是否有记录它的必要?显然没有,这就是AOF的重写机制。它会根据实际情况进行重写。

同样还是fork一个子进程,然后子进程继承了父进程当前的数据,所以子进程就会按照AOF的文本要求,将内存中的数据记录到新的AOF文件中,当然了,新的数据操作父进程也不会闲着,父进程会将新的数据操作记录到aof_rewrite_buf这个缓冲区里面,然后子进程写完了之后会通过信号通知父进程它写完了,这个时候再父进程把aof_rewrite_buf的数据合并到新的AOF文件中。这个时候就可以用新的AOF代替旧的。

不过这个旧的AOF文件可是不敢删除的,并且还是要写的,万一服务器突然挂了,新的AOF文件不完整,还能有个旧的AOF文件兜兜底。

这里我们可以简单的区分一下AOF和RDB的差别了,RDB对fork之后的数据就不管了,AOF通过缓冲区的机制会实时保存,这里其实就是RDB定期备份和AOF实时备份的一个差别了,当然,我们还是要通过实际情况应用的。

当AOF和RDB文件同时存在的时候,因为AOF文件信息更全,所以是以AOF为主的

可是当重写数据的时候,因为文本方式写入开销有的时候挺大的,Redis就引入了混合持久化的操作,即Redis在重写的时候,子进程会将父进程当前的内存数据按照RDB的方式,即二进制的方式写入到AOF文件中。

这就是混合持久化,我们可以验证一下。

首先我们要开启混合持久化的配置选项:

使用命令bgrewriteaof进行重写。然后再进行一些数据操作

我们就能发现确实AOF文件变成了我们想要的样子。

特性AOF(Append Only File)RDB(Redis DataBase)AOF 更全的理由
持久化内容每条写命令(SET、DEL 等)某个时间点的内存数据快照记录了所有写入“过程”,不是只看最终值
触发方式每条命令 / 每秒 / 系统控制手动 SAVE / 自动定时 SAVEAOF 写得更频繁,更新更实时
丢失数据可能性极低(可每秒甚至每次写入刷新)有(取决于快照频率)AOF 通常最多丢失 1 秒内数据,RDB 可丢分钟数据
文件大小大,命令多,冗余高小,只含最终结构数据AOF 为了完整性记录全部操作
恢复速度慢(执行命令)快(直接加载)尽管慢,但更精细
内容可读性高(Redis 命令文本)低(二进制格式)可直接编辑、分析、还原或回滚
手动修复灵活性高,可编辑命令以排错或回滚低,损坏则难以修复AOF 可删除误操作命令,回滚到期望状态
适用场景数据极其重要、希望尽量减少数据丢失对性能要求高、容忍短时数据丢失AOF 更适用于对数据恢复完整性要求高的系统

以上算是一个总结。


感谢阅读!

相关文章:

  • 配置 Nginx 的 HTTPS
  • 分布式理论和事务
  • Python常用的第三方模块之【jieba库】支持三种分词模式:精确模式、全模式和搜索引擎模式(提高召回率)
  • 从Nacos derby RCE学习derby数据库的利用
  • 【Linux】冯诺依曼体系结构及操作系统架构图的具体剖析
  • Redisson Watchdog实现原理与源码解析:分布式锁的自动续期机制
  • 蚊子的搜索距离可达60公里:对一些特殊气味有所偏爱
  • vue3 el-table 右击
  • 深入理解 java synchronized 关键字
  • 用高斯溅射技术跨越机器人模拟与现实的鸿沟:SplatSim 框架解析
  • 本文通俗简介-优雅草星云物联网AI智控系统软件介绍-星云智控是做什么用途的??-优雅草卓伊凡
  • 基于ZU15EG+ADRV9009的无人机平台
  • C++23 新特性:令声明顺序决定非静态类数据成员的布局 (P1847R4)
  • Visual Studio2022 配置 SDL3及拓展库
  • 从DVP、LVDS到MIPI:视频传输接口全解析
  • Unity ML-Agents + VScode 环境搭建 Windows
  • AI大模型学习十一:‌尝鲜ubuntu 25.04 桌面版私有化sealos cloud + devbox+minio,实战运行成功
  • 工业/电网场景如何选择合适的储能协调控制器方案?
  • 基于python代码的通过爬虫方式实现tiktok发布视频(2025年4月)
  • 第六章 QT基础:4、QT的TCP网络编程
  • 美联储褐皮书:关税政策背景下,美国部分地区物价上涨、经济前景恶化
  • 读图丨漫游者秦龙,一生为经典画插图
  • 北京朝阳法院:未经许可使用他人剧本语句和情节构成侵权
  • 富力地产:广州富力空港假日酒店第一次拍卖流拍,起拍价约2.77亿元
  • 平均25岁,天津茱莉亚管弦乐团进京上演青春版《春之祭》
  • 被指违反代理协议遭南航暂停售票资格, 去哪儿网:今起恢复