redis之持久化

持久化

前言:简单来说就是,redis内存和硬盘两边都存。插入数据时,内存硬盘都写入,查询数据时,直接从内存读取,硬盘的数据只是redis在重新启动的时候来恢复内存中的数据的

代价就是消耗更多空间。

RDB:Redis DataBase 定期备份

RDB 持久化是把当前进程数据生成快照保存到硬盘的过程,触发 RDB 持久化过程分为手动触发和 自动触发。

save手动触发

阻塞当前 Redis 服务器,直到 RDB 过程完成为止,对于内存比较大的实例造成长时间 阻塞,基本不采用。

bgsave手动触发

此处为并发编程的场景,redis使用的是多进程的方式来完成的并发编程,来完成bgsave的实现

Redis 进程执行 fork 操作创建子进程,RDB 持久化过程由子进程负责,不会影响Redis服务器处理其他客户端的请求和命令,子进程处理完成后自动 结束。阻塞只发生在 fork 阶段,一般时间很短。

  1. 执行 bgsave 命令,Redis 父进程判断当前进是否存在其他正在执行的子进程,如 RDB/AOF 子进 程,如果存在 bgsave 命令直接返回。

  2. 父进程执行 fork 创建子进程,fork 过程中父进程会阻塞,通过 info stats 命令查看 latest_fork_usec 选项,可以获取最近一次 fork 操作的耗时,单位为微秒。

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

  4. 子进程创建 RDB 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执 行 lastsave 命令可以获取最后一次生成 RDB 的时间,对应 info 统计的 rdb_last_save_time 选 项。

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

RDB 文件的处理

保存:RDB 文件保存再 dir 配置指定的目录(默认 /var/lib/redis/)下,文件名通过 dbfilename 配置(默认 dump.rdb)指定。可以通过执行 config set dir {newDir} 和 config set dbfilename {newFilename} 运行期间动态执行,当下次运行时 RDB 文件会保存到新目录。

压缩:Redis 默认采用 LZF 算法对生成的 RDB 文件做压缩处理,压缩后的文件远远小于内存大 小,默认开启,可以通过参数 config set rdbcompression {yes|no} 动态修改。

redis的触发时机:

1、手动(save,bgsave),注意,直接使用save是不会触发子进程&文件替换逻辑的

2、自动(配置文件中,如下图)

修改后需要重启redis服务器才能生效

注意:虽然压缩 RDB 会消耗 CPU,但可以大幅降低文件的体积,方便保存到硬盘或通过网络发送到 从节点,因此建议开启。

校验:如果 Redis 启动时加载到损坏的 RDB 文件会拒绝启动。这时可以使用 Redis 提供的 redischeck-dump 工具检测 RDB 文件并获取对应的错误报告。

RDB优缺点:

• RDB 是一个紧凑压缩的二进制文件,代表 Redis 在某个时间点上的数据快照。非常适用于备份,全 量复制等场景。比如每 6 小时执行 bgsave 备份,并把 RDB 文件复制到远程机器或者文件系统中 (如 hdfs)用于灾备。

• Redis 加载 RDB 恢复数据远远快于 AOF 的方式。

• RDB 方式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运行都要执行 fork 创建子进 程,属于重量级操作,频繁执行成本过高。通过AOF解决以下问题

• RDB 文件使用特定二进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有风 险。

另外:

假如把rdb文件损坏,比如破坏里面的二进制数据,再kill后会发现服务器无法启动,发生这种服务器挂掉的情况,可以查看 /var/log/redis/下的redis-server.log

redis提供了rdb文件的检查工具:redis-check-rdb ,可以先通过该工具,检查rdb文件格式是否符合要求

AOF:Append Only File 实时备份

AOF(Append Only File)持久化:以独立日志的方式记录每次写命令,重启时再重新执行 AOF 文件中的命令达到恢复数据的目的。AOF 的主要作用是解决了数据持久化的实时性,目前已经是Redis 持久化的主流方式。理解掌握好 AOF 持久化机制对我们兼顾数据安全性和性能非常有帮助。注意AOF存储的是文本格式,这点与RDB的二进制存储不同

AOF类似于MySQL的binlog,他会把用户的每个操作都记录到文件中,redis重新启动的时候就会读取aof文件的内容。注意开启aof的时候rdb就不生效了

使用AOF

开启 AOF 功能需要设置配置:appendonly yes,默认不开启。AOF 文件名通过 appendfilename 配置(默认是 appendonly.aof)设置。修改后重新启动redis生效

AOF 的工作流程操作:命令写入(append)、文件同步(sync)、文件重写 (rewrite)、重启加载(load)

  1. 所有的写入命令会追加到 aof_buf(缓冲区)中。

  2. AOF 缓冲区根据对应的策略向硬盘做同步操作。

  3. 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。

  4. 当 Redis 服务器启动时,可以加载 AOF 文件进行数据恢复。

1. 所有的写入命令会追加到 aof_buf(缓冲区)中。

为什么需要 aof_buf 这个缓冲区?Redis 使用单线程响应命令,如果每次写 AOF 文件都直 接同步硬盘,性能从内存的读写变成 IO 读写,必然会下降。先写入缓冲区可以有效减少 IO 次数。

对于一些极端情况,比如将数据写入缓冲区的过程中,此时数据仍在内存里,如果此时金钟挂掉了此时数据就会丢失,但是仍有一些方法来规避该风险:**Redis 提供多种缓冲区同步策略,让用户根据自己的需求做出合理的平衡。**比如设置的刷新频率越高,数据的可靠性就越高,但同时对性能的影响也会更高,这其实是一种取舍策略。类似于mysql的事务,隔离级别等等

2. AOF 缓冲区根据对应的策略向硬盘做同步操作。

Redis 提供了多种 AOF 缓冲区同步文件策略,由参数 appendfsync 控制

everysec:每秒执行一次。这也是默认模式。

3. 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。

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

AOF重写机制:write(核心,redis启动时只关注最终结果,该机制就是确保最终的结果达到最佳)

• 进程内已超时的数据不再写入文件。

• 旧的 AOF 中的无效命令,例如 del、hdel、srem 等重写后将会删除,只需要保留数据的最终版 本。

• 多条写操作合并为一条,例如 lpush list a、lpush list b、lpush list 从可以合并为 lpush list a b c。 较小的 AOF 文件一方面降低了硬盘空间占用,一方面可以提升启动 Redis 时数据恢复的速度。

AOF 重写过程可以手动触发和自动触发:

• 手动触发:调用 bgrewriteaof 命令。

• 自动触发:根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定自动触发时 机。

◦ auto-aof-rewrite-min-size:表示触发重写时 AOF 的最小文件大小,默认为 64MB。

◦ auto-aof-rewrite-percentage:代表当前 AOF 占用大小相比较上次重写时增加的比例。

  1. 执行 AOF 重写请求。 如果当前进程正在执行 AOF 重写,请求不执行。如果当前进程正在执行 bgsave 操作,重写命令 延迟到 bgsave 完成之后再执行。

  2. 父进程执行 fork 创建子进程。

  3. 重写

a. 主进程 fork 之后,继续响应其他命令。所有修改操作写入 AOF 缓冲区并根据 appendfsync 策 略同步到硬盘,保证旧 AOF 文件机制正确。

b. 子进程只有 fork 之前的所有内存信息,父进程中需要将 fork 之后这段时间的修改操作写入 AOF 重写缓冲区中。

  1. 子进程根据内存快照,将命令合并到新的 AOF 文件中。

  2. 子进程完成重写

a. 新文件写入后,子进程发送信号给父进程。

b. 父进程把 AOF重写缓冲区内临时保存的命令追加到新 AOF 文件中。

c. 用新 AOF 文件替换老 AOF 文件。

fork()创建子进程后,父进程 同时进行的两项核心工作 ,以及子进程 进行的一项工作。这三条并行的主线是:

  1. **主线一(父进程 - 持续服务):**​ 父进程继续正常接收并处理客户端的新请求。

  2. 主线二(父进程 - 记录增量): ​ 父进程将这些新请求产生的 AOF 日志,写入一个专用的 AOF 重写缓冲区

  3. 主线三(子进程 - 生成快照): ​ 子进程基于 fork()时继承的内存数据快照,将其转换成 AOF 格式,并写入一个全新的 AOF 文件。

父进程fork之后,就已经让子进程写心得aof文件了,且随着时间推移,子进程写完新的aof文件后将会替换掉旧的aof文件,是否意味着父进程写的这个旧的即将被销毁的aof文件毫无意义?

为非如此,因为需要考虑极端情况,假设在重写过程中途服务器挂了,子进程的数据就会丢失且新的aof文件不完整,所以父进程坚持写旧的aof文件,就是确保了服务器中途挂掉后重启时的数据完整性。

混合持久化

redis上同时存在aof和rdb快照的时候,以aof为主

总结:

  1. Redis 提供了两种持久化方案:RDB 和 AOF。

  2. RDB 视为内存的快照,产生的内容更为紧凑,占用空间较小,恢复时速度更快。但产生 RDB 的开 销较大,不适合进行实时持久化,一般用于冷备和主从复制。

  3. AOF 视为对修改命令保存,在恢复时需要重放命令。并且有重写机制来定期压缩 AOF 文件。

  4. RDB 和 AOF 都使用 fork 创建子进程,利用 Linux 子进程拥有父进程内存快照的特点进行持久化, 尽可能不影响主进程继续处理后续命令。

相关推荐
Lentou2 小时前
Prompt提示词相关教程
数据库·prompt
2401_837163892 小时前
CSS如何处理带有状态切换的折叠菜单_利用BEM修饰符管理状态
jvm·数据库·python
eLIN TECE2 小时前
Redis重大版本整理(Redis2.6-Redis7.0)
java·数据库·redis
m0_617881422 小时前
Navicat连接MariaDB报1045密码错误怎么办_权限排查与解决
jvm·数据库·python
m0_515098422 小时前
C#怎么操作WPF数据模板 C#如何用DataTemplate定义集合项的显示样式和布局【控件】
jvm·数据库·python
qq_654366982 小时前
golang如何实现告警分级与升级_golang告警分级与升级实现步骤
jvm·数据库·python
2401_897190552 小时前
Redis怎样在Spring中执行批量Pipeline指令
jvm·数据库·python
西敏寺的乐章2 小时前
大模型 Prompt 体系与调参完全指南:System/User/Tools Prompt 区别与推理参数实战
数据库·人工智能·prompt
2301_815279522 小时前
使用 Go 语言安全高效地将 SSH 公钥复制到远程服务器
jvm·数据库·python