Mr Dk.'s BlogMr Dk.'s Blog
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • ⛸️ Redis Implementation
    • Part 1 - 数据结构与对象

      • Chapter 2 - 简单动态字符串
      • Chapter 3 - 链表
      • Chapter 4 - 字典
      • Chapter 5 - 跳跃表
      • Chapter 6 - 整数集合
      • Chapter 7 - 压缩列表
      • Chapter 8 - 对象
    • Part 2 - 单机数据库的实现

      • Chapter 9 - 数据库
      • Chapter 10 - RDB 持久化
      • Chapter 11 - AOF 持久化
      • Chapter 12 - 事件
      • Chapter 13 - 客户端
      • Chapter 14 - 服务器
    • Part 3 - 多机数据库的实现

      • Chapter 15 - 复制
      • Chapter 16 - Sentinel
      • Chapter 17 - 集群
    • Part 4 - 独立功能的实现

      • Chapter 18 - 发布与订阅
      • Chapter 19 - 事务
      • Chapter 21 - 排序
      • Chapter 22 - 二进制位数组
      • Chapter 23 - 慢查询日志

Chapter 10 - RDB 持久化

Created by : Mr Dk.

2020 / 06 / 03 10:14

Nanjing, Jiangsu, China


RDB 持久化功能可以将 Redis 内存中的数据库状态保存到磁盘中。具体做法是生成一个压缩的二进制 RDB 格式文件,通过这个文件,可以还原当时的数据库状态。

SAVE and BGSAVE

SAVE 和 BGSAVE 两条命令都可以用于生成 RDB 文件:

  • SAVE 阻塞 Redis 服务器进程,直到 RDB 文件创建完毕,期间服务器无法处理任何请求
  • BGSAVE 创建了一个子进程负责 RDB 文件的写入,服务器进程继续处理请求
    • 期间 SAVE / BGSAVE / GBREWRITEAOF 命令会被拒绝,防止产生竞争条件

由于 AOF 持久化的频率比 RDB 高,因此只有 AOF 持久化功能关闭时,服务器才使用 RDF 文件来还原数据库状态。

Automatic Saving

Redis 允许用户通过设置服务器的 save 选项,让服务器每隔一段时间自动执行一次 BGSAVE。save 属性中可以设置保存多个条件,只要有一个条件被满足,服务器就会执行 BGSAVE 命令。默认的条件如下,含义为 xxx 秒内对数据库进行了 xxx 次修改后触发:

save 900 1
save 300 10
save 60 10000

这些条件保存在 redisServer 结构体中:

struct redisServer {
    // ...
    struct saveparam *saveparams;
    // ...
};

这个结构体数组中的每个元素保存了一个 save 选项的条件:

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

另外,服务器还维护以下两个相关属性:

struct redisServer {
    // ...
    long long dirty; // 修改计数器,每修改一次 +1
    time_t lastsave; // 上次进行持久化操作的时间
    // ...
}

Redis 服务器的周期性操作函数默认 100ms 执行一次,会对 save 选项下的每一个条件进行检查:

  • 计算当前时间与 lastsave 的时间差
  • 计算在一定的时间间隔内,Redis 修改次数是否满足条件
  • 如果满足条件,那么执行 BGSAVE,dirty 计数器被重置为 0

RDB 文件结构

完整的 RDB 文件包含以下部分:

  • REDIS (magic value)
  • db_version (RDB 第六版)
  • databases - 每一个非空数据库
  • EOF - RDB 正文内容结束
  • check_sum - 对前四个部分计算得到的校验和

其中,每一个非空数据库的文件结构:

  • SELECTDB (magic value)
  • db_number - 数据库编号
  • key_value_pairs

而每个 key_value_pairs 的结构:

  • 不带过期时间:
    • TYPE (magic value)
    • key
    • value
  • 带有过期时间:
    • EXPIRETIME_MS (magic value)
    • ms - 毫秒 UNIX 时间戳
    • TYPE (magic value)
    • key
    • value

其中,TYPE 用于解析 value 的类型,因为 key 一定是字符串。

Edit this page on GitHub
Prev
Chapter 9 - 数据库
Next
Chapter 11 - AOF 持久化