Redis - Redis持久化:AOF和RDB

news/2024/10/25 13:24:09/

1. 为什么要持久化

  • Redis是内从数据库,宕机后数据会丢失;
  • Redis重启后,为了快速恢复数据,提供了持久化机制;
  • Redis有两种持久化方式:RDB和AOF,这也是Redis无畏宕机与快速恢复数据的杀手锏。

注意:Redis持久化不保证数据的完整性。

当Redis用作DB时,DB数据要完整,所以一定要有一个完成的数据源(文件、MySQL),在系统重启时,从这个完整的数据源中将数据load到Redis中。

2. RDB 快照,让宕机快速恢复

2.1 RDB(Redis DataBase)

RDB(Redis DataBase)是Redis默认的持久化方式。Redis将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。

在做数据恢复时,直接将 RDB 文件中的数据读入内存完成恢复。

2.2 触发快照的方式

  1. 符合自定义配置的快照规则

在 redis.conf 中配置:N 秒内数据集至少有 M 个改动,这一条件被满足时,自动保存一次数据集

# save 3600 1
# save 300 100
# 60 秒内有至少有 1000 个键被改动这一条件时, 自动保存一次数据集
save 60 10000
  1. 命令显示触发,执行 save 或者 bgsave 命令

还可以手动执行命令生成RDB快照,进入 Redis 客户端执行命令 save 或 bgsave 可以生成 dump.rdb 文件, 每次命令执行都会将所有 Redis 内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。

bgsave的写时复制(COW)机制

Redis 借助操作系统提供的写时复制技术(Copy-On-Write, COW),在生成快照的同时,依然可以正常 处理写命令。简单来说,bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。 bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。此时,如果主线程对这些 数据也都是读操作,那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据,那么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

save与bgsave对比:

在这里插入图片描述
配置自动生成rdb文件后台使用的是bgsave方式。

  1. 执行 flushall 命令

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

  1. 执行主从复制操作 (第一次)

2.3 RDB持久化流程

在这里插入图片描述

  1. Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof(aof文件重写命令)的子进程,如果在执行则bgsave命令直接返回。

  2. 父进程执行fork(调用OS函数复制主进程)操作创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令。

  3. 父进程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令。

  4. 子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换。(RDB始终完整)

  5. 子进程发送信号给父进程表示完成,父进程更新统计信息。

  6. 父进程fork子进程后,继续工作。

2.4 RDB的优缺点

2.4.1 优点

  • 适合大规模数据恢复
  • 对数据完整性和一致性要求不高更适合使用
  • RDB 采⽤⼆进制 + 数据压缩的⽅式写磁盘,⽂件体积⼩,数据恢复速度快

2.4.2 缺点

  • Fork的时候,内存中的数据会被克隆一份,大致2倍的膨胀,需要考虑;

  • 虽然Redis在fork的时候使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能;

  • 不保证数据完整性,在备份周期在一定间隔时间做一次备份,所以如果 Redis 意外 down 的话,会丢失最后一次快照以后更改的所有数据。

3. AOF(append-only file),避免宕机数据丢失

3.1 AOF是什么

快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失 最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方 式: AOF 持久化,将修改的每一条指令记录进文件 appendonly.aof 中(先写入 os cache,每隔一段时间 fsync 到磁盘)。

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

3.2 AOF持久化实现

配置 redis.conf

# 可以通过修改redis.conf配置文件中的appendonly参数开启 
appendonly yes 
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。 
dir /path
# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改 
appendfilename "appendonly.aof"

3.3 AOF持久化流程

  1. 命令写入(append)

客户端的请求写命令会被 append 追加到 aof_buf 缓冲区内

  1. 文件同步(sync)

AOF 缓冲区会根据 AOF 持久化策略 [always, everysec, no] 将操作 sync 同步到磁盘的 AOF 文件中

  1. 文件重写(rewrite)

AOF 文件大小超过重写策略或手动重写时,会对 AOF 文件进行重写(rewrite),压缩 AOF 文件容量

  1. 重启加载(load)

Redis 服务器重启时,会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的

3.4 AOF原理

3.4.1 AOF是如何实现的

AOF文件中存储的是redis的命令,同步命令到 AOF 文件的整个过程可以分为三个阶段:

命令传播: Redis 将执行完的命令、命令的参数、命令的参数个数等信息发送到 AOF 程序中。

缓存追加: AOF 程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的 AOF 缓存中。

文件写入和保存: AOF 缓存中的内容被写入到 AOF 文件末尾,如果设定的 AOF 保存条件被满足的话,fsync 函数或者 fdatasync 函数会被调用,将写入的内容真正地保存到磁盘中。

命令传播

当一个 Redis 客户端需要执行命令时, 它通过网络连接, 将协议文本发送给 Redis 服务器。服务器在接到客户端的请求之后, 它会根据协议文本的内容, 选择适当的命令函数, 并将各个参数从字符串文本转换为 Redis 字符串对象( StringObject )。每当命令函数成功执行之后, 命令参数都会被传播到AOF 程序。

缓存追加

当命令被传播到 AOF 程序之后, 程序会根据命令以及命令的参数, 将命令从字符串对象转换回原来的协议文本。协议文本生成之后, 它会被追加到 redis.h/redisServer 结构的 aof_buf 末尾。

redisServer 结构维持着Redis 服务器的状态, aof_buf 域则保存着所有等待写入到 AOF 文件的协议文本(RESP)。

文件写入和保存

每当服务器常规任务函数被执行、 或者事件处理器被执行时, aof.c/flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作:
WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件。
SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。

3.4.2 AOF日志记录的内容有哪些?

当 Redis 接受到 “set key value” 命令将数据写到内存后,Redis 会按照如下格式写⼊ AOF ⽂件。

这是一种resp协议格式数据,星号后面的数字代表命令有多少个参数,$号后面的数字代表这个参数有几个字符。

  • *3:命令有3个部分
  • $3:后面紧跟具体的指令,指令的字长

在这里插入图片描述

3.4.3 AOF保存模式 - 三种写入策略

可以在 redis.config 中配置 Redis 多久将数据 fsync 到磁盘一次:

# If unsure, use "everysec".
# 每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非常安全。
# appendfsync always
# 每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据。
appendfsync everysec
# 从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择:
# appendfsync no

推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

always 策略在实践中非常慢,但它支持组提交,因此如果有多个并行的写入操作,Redis 将尝试执行单个 fsync 操作。

3.5 AOF重写

3.5.1 AOF重写机制介绍

随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入了AOF重写机制压缩文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。

3.5.2 AOF重写机制原理

重写后的AOF文件为什么可以变小?有如下原因:

  1. 进程内已经超时的数据不再写文件。

  2. 旧的AOF文件含有无效命令,比如,我们调用INCR test命令100次,文件中就必须保存全部的100条命令,但其实99条都是多余的。因为要恢复数据库的状态其实文件中保存一条SET test 100就够了。

  3. 多条写命令可以合并为一个,如:lpush list a、lpush list b、 lpush list c 可以转化为:lpush list a b c。

为了防止合并的数据过大造成客户端缓冲区溢出,对于list、set、hash、zset等类型,以64个元素为界拆分为多条。

  • AOF 重写实现:
    在这里插入图片描述

  • Redis 7.0 中 Multi Part AOF 实现:
    在这里插入图片描述

3.5.3 触发 AOF 重写方式

  1. Redis 客户端手动触发

进入redis客户端执行命令 bgrewriteaof 重写AOF

  1. 配置 redis.config
# aof 文件自上一次重写后文件大小增长了100%,则再次触发重写机制,比如说,上次AOF文件容量为100M,这次文件已经到200M了,则自动触发重写机制
auto-aof-rewrite-percentage 100
# aof 文件至少要达到64M才会触发自动重写,文件太小,恢复速度很快,重写意义不大
auto-aof-rewrite-min-size 64mb

3.6 AOF 的优缺点

优点

具有更高的数据安全性,AOF 默认同步策略为每秒同步一次,因此即使 Redis 服务出现问题,那么最多也只会丢失最近一秒内修改的数据。AOF 文件采用追加的形式进行保存,因此即使在写入过程中出现问题,也不会破坏日志文件中已经存在的内容;如果当我们的写入过程只进行了一半就出现了问题,那么在下一次 Redis 启动之前,我们可以通过 redis-check-aof 工具来帮助我们解决数据一致性的问题当日志文件过大时,我们可以通过重写机制来对 AOF 文件进行重写AOF 文件有序地保存了对数据库执行的所有写入操作,格式十分清晰,易于理解

缺点

  • 数据的完整性和一致性更高相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB在恢复大数据集时的速度比 AOF 的恢复速度要快。

  • 同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。当我们采用同步禁用 (appendfsync no) 策略时,其效率和 RDB 相同

  • 数据的完整性和一致性更高因为AOF记录的内容多,文件会越来越大,数据恢复也会越来越慢。

  • 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

4. RDB 和 AOF 对比

在这里插入图片描述

  • 官方推荐2个都启用

  • 内存数据库:使用 rdb+aof - 数据不容易丢

  • 用作缓存服务器,对数据不敏感:使用rdb - 性能高

  • 不建议只使用 aof - 性能差

  • 在数据还原时:有rdb+aof,则还原aof,因为RDB会造成文件的丢失,AOF相对数据要完整。只有rdb,则还原rdb。

  • 追求高性能:都不开,redis宕机则从数据源恢复

5. Redis 4.0 混合持久化

重启 Redis 时,我们很少使⽤ rdb 来恢复内存状态,因为会丢失⼤量数据。我们通常使⽤ AOF ⽇志重放,但是重放 AOF ⽇志性能相对 rdb 来说要慢很多,这样在 Redis 实例很⼤的情况下,启动需要花费很⻓的时间。

Redis 4.0 为了解决这个问题,带来了⼀个新的持久化选项——混合持久化。将 rdb ⽂件的内容和增量的 AOF ⽇志⽂件存在⼀起。这⾥的 AOF ⽇志不再是全量的⽇志,⽽是⾃持久化开始到持久化结束的这段时间发⽣的增量 AOF ⽇志,通常这部分 AOF ⽇志很⼩。

在 redis.conf 文件可以开启混合持久化(必须先开启aof

# aof‐use‐rdb‐preamble yes

如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将 重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一 起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改 名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,因此重启效率大幅得到提升。

混合持久化AOF文件结构如下
在这里插入图片描述


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

相关文章

5G MEC UPF选择及本地分流技术分析

【摘 要】边缘计算的本质是一场架构革命,为满足超低时延和超大带宽等业务需求,应用从传统Client-Server架构转向Client-Edge-Server三级架构,实现云网融合。在5G网络中,如何为边缘应用选择合适的UPF,实现高效的本地分流成为关键问题。为解决这个问题,分析了采用5G核心网…

vue-element 表单校验

1. 表单校验 完整的表单校验需要三个组件完成配合,分别是el-form,el-form-item,表单项,如el-input el-form 负责绑定model和rulesel-form-item 负责绑定propel-input 负责双向绑定具体的表单数据 手动兜底校验 1.1 表单项校验 1.1.1 内置校验规则 在Rules:{}中给每一个需要…

Godzilla(哥斯拉)安装与使用

Godzilla安装与使用1.Godzilla介绍2.Godzliia下载与安装2.1.Godzilla下载2.2.运行环境2.3.Godzilla安装2.3.1.执行文件2.3.2.安装完成3.Godzliia3.1.Godzliia使用3.1.1.生成木马3.1.2.存储木马3.1.3.放入木马3.1.4.访问木马3.1.5.连接木马3.1.6.测试连接3.1.7.连接进入3.2.Godz…

要学的东西太多了怎么办

一、前言 为什么要写这篇博客,一方面是自己最近遇到一些事情然后刚想清楚,一方面是跟以前的同事朋友们聊天,发现他们都很沮丧,感叹学不完的知识以及焦虑年龄会影响职业生涯。在群上劝他们的我似乎成了那个唯一的奋斗逼&#xff0c…

单片机——LED

0. 单片机编程的一般步骤 目标分析:点亮开发板上的LED灯 电路原理图分析:相关器件的工作原理 数据手册分析:IO端口控制 代码编写、编译 下载与调试 1. LED简介 Led:即发光二极管,具有单向导通性,一般…

RK3568下载SDK编译源码

前面我们已经搭建好了编译一个环境https://blog.csdn.net/qq_24093081/article/details/128394606 所以在这里我们就需要下载瑞芯微提供的SDK进行编译,由于RK3568支持多种系统,比如Android11,Linux(debian、Ubuntu、buildroot、yo…

Numpy+PIL实现图片的自由旋转

1.内容简介 使用PIL和Numpy编程实现图片的自由旋转。 2.技术要点 (1)用Python PIL库将图片读取为NumPy 数组。 (2)采用旋转后图像幅面放大的图像旋转变换方式,根据旋转角度和原图像尺寸计算图像像素点的旋转变换矩阵…

Feign和restTemplate 单个接口超时拦截处理

文章目录1. Feign超时2. restTemplate超时(全局)3. restTemplate超时(指定接口,用注解实现切面拦截)以5s超时为例。超时的接口数据,就不要了,默认为空1. Feign超时 feign:client:config:defaul…