Redis 「3」持久化

216 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

Redis 持久化方案中有两种模式:基于快照 RDP 和基于写日志 AOF。接下来让我们一探究竟吧。

01-RDB

Redis 中有两个命令可以生成 RDB 持久化文件:

  • SAVE,Redis 服务器会被阻塞,直至 RDB 文件生成完毕;此间所有的客户端请求都将被拒绝。
  • BGSAVE,Redis 服务器创建子进程生成 RDB 文件。此期间 Redis 服务器继续处理客户端请求。

自动间隔性保存配置

save 900 1        # 900s 内至少 1 次保存
save 300 10       # 300s 内至少 10 次保存
save 60  10000    # 60s 内至少 10000 次保存

实现原理,redisServer 中存在记录上述配置的数组struct saveparam *saveparams;,每个元素结构为:

struct saveparam {
	time_t seconds;    // 秒数
	int changes;       // 修改数
};

而且 redisServer 中记录了修改计数器long long dirty和上次save操作的时间time_t lastsave。Redis 服务器中的周期性操作函数 serverCron 每隔100毫秒就会执行一次,执行时会计算举例上次执行 save 操作的间隔,并且遍历 saveparams 数组,检查条件是否满足,若满足则执行BGSAVE

01.1-RDB 文件结构

RDB 文件的结构

Linux 上可以通过 od 命令分析 *.rdb 文件。

02-AOF

AOF 模式下持久化分为三个步骤:

  1. 命令追加

    redisServer 中存在一个结构sds aof_buf称为 AOF 缓冲区。当客户端的写命令被执行时,基于文本协议的命令会追加到aof_buf中。

  2. 文件写入

    在事件循环中,每次事件处理后,都会调用flushAppendOnlyFile()方法,将aof_buf中的内容写入 AOF 文件中。

    flushAppendOnlyFile()方法的行为由appendfsync配置项控制,该配置项有三种可选值:

    • always,将aof_buf中内容写入并同步到 AOF 文件
    • everysec,将aof_buf中内容写入文件,如果据上次同步时间超过1秒,则再次进行同步。
    • no,将aof_buf中内容写入文件,但不同步,何时同步由操作系统决定。
  3. 文件同步

    文件的写入与同步 现在操作系统中,为缓解磁盘与内存、CPU之间的写入速度差异,当用户调用write方法将内容写入到文件中时,会优先写入到内存中的一块缓冲区中,等缓冲区满或超过了指定时间后,才真正将数据写入到磁盘上的文件中。

02.1-AOF 文件的载入

Redis 启动时,默认优先读取 AOF 文件来恢复数据。读取 AOF 文件并还原数据库的步骤如下:

  1. 创建一个不带网络连接的伪客户端
  2. 从 AOF 文件中读取并解析一条写命令
  3. 使用伪客户端提交写命令到服务端
  4. 一直重复2-3步骤,直到 AOF 文件结束。

02.2-AOF 文件重写

AOF 文件的一个缺点是随着运行时间的增长文件的大小会逐渐变大。体积过大的 AOF 文件可能会对服务器产生较大的压力。

AOF 重写会创建一个子进程,父进程继续处理客户端的请求。子进程重写期间,父进程处理的请求会被写入到 AOF 重写缓冲区中,待子进程完成重写后,再追加到新的 AOF 文件中。

新的 AOF 文件创建完成后,会原子地将旧文件替换为新文件。


往期文章

Redis 「2」缓存一致性与异常处理

Redis 「1」流水线、事务、Lua 脚本

Java Basic「3」使用 Java IO API 创建 C/S 程序的方法

Java Basic「2」Java中的反射

Java Basic「1」JCF 及常见问题