Redis 中的持久化技术《Redis设计与实现》

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 本篇将介绍 Redis 中的持久化技术,主要有两种: RDB持久化 和 AOF持久化

本篇将介绍 Redis 中的持久化技术,主要有两种: RDB持久化AOF持久化


1、RDB 持久化


1.1 RDB 文件的创建与载入


Redis使用 SAVEBGSAVE 命令生成 RDB 文件;

SAVE :会阻塞 Redis 服务器进程,直到 RDB 文件创建完毕为止,阻塞期间服务器不能处理任何命令请求;

BGSAVE :会派生一个子进程,由子进程负责创建 RDB 文件,父进程继续处理命令请求。BGSAVE 执行期间,会发生以下特殊情况:

  • BGSAVE 命令执行期间,客户端发送 SAVEBGSAVE 命令会被服务器拒绝,防止产生竞争条件。客户端发送 BGREWRITEAOF 命令会被延迟;
  • BGREWRITEAOF 命令执行期间,客户端发送 BGSAVE 命令会被服务器拒绝;

创建 RDB 文件由 rdb.c/rdbSave 函数完成;

载入 RDB 文件由 rdb.c/rdbLoad 函数完成;

RDB 文件的载入工作是在服务器启动时自动执行,只要 Redis 服务器在启动时检测到 RDB 文件存在,就会自动载入 RDB 文件;

AOF 文件的更新频率通常比 RDB 文件更新频率高:

  • 当服务器开启了 AOF 持久化功能时,会优先使用 AOF 文件还原数据库状态;
  • 当服务器关闭了 AOF 持久化的功能时,才会使用 RDB 文件来还原数据库状态;
  • 服务器在载入 RDB 文件期间,会一直处于阻塞状态,直到载入工作完成为止;


1.2 自动间隔性保存


1.2.1 设置保存条件
  • 服务器会根据 save 选项所设置的保存值,设置服务器状态 redisServer 结构的 saveparams 属性;
  • redisServer 的结构定义:structredisServer{ //... //记录了保存条件的数组structsaveparam *saveparams; // }
  • saveparams 属性是一个数组,每个 saveparam 结构保存了一个 save 设置的保存条件;
  • saveparam 的结构定义:structsaveparam{ //秒数 time_t seconds; //修改值 int changes; }

2648c785a38b8382db5c4bfc43988633.jpg

1.2.2 dirty 计数器和 lastsave 属性
  • dirty 属性和 lastsave 属性在 redisServer 结构体里:struct redisServer{//... //修改计数器 longlong dirty; //上一次执行保存的时间 time_tlastsave; };dirty 计数器记录距离上一次成功执行 SAVE 命令或者 BGNAME命令之后,服务器对数据库状态进行了多少次修改;lastsave 属性是一个 UNIX 时间戳,记录了服务器上一次成功执行 SAVE 命令或 BGSAVE 命令的时间;
1.2.3 检查保存条件是否满足
  • Redis 服务器周期性操作函数 serverCron 默认每隔 100ms 会执行一次,其中包括检查 save 选项所设置的保存条件是否满足(遍历并检查 saveparams数组中的所有保存条件),满足则执行 BGSAVE 命令;


1.3 RDB 文件


1.3.1 RDB 的文件结构
  • RDB 文件结构的逻辑图:
  • 各个字段含义:

f73aade7374c906576c81e9035107391.jpg

Redis 中的持久化技术《Redis设计与实现》

1.3.2 database 的文件结构
  • database 为 RDB 文件的结构组成部分;
  • databases 部分的逻辑结构:

472d589e9cbae8a536af0d40f5b1c211.png

各字段含义:

16d099d6d517856ea28fcfc184cd780c.jpg

1.3.3 key_value_pairs 的文件结构
  • key_value_pairs 为 databases 的结构组成部分;有两种类型,一种不带过期时间,一种带过期时间;
  • key_value_pairs 部分的逻辑结构:

3a9c4ff024648f4b5494db8dfe69c0b7.png

各字段含义:

42a375eaa802bb3cdd581ce7d897c321.jpg

1.3.4 value 的编码
  • value 为 key_value_pairs 的结构组成成分;
  • value 对象的结构和长度会根据 TYPE 类型的不同而不同;
  • value可以是 字符串对象列表对象集合对象哈希表对象有序集合对象INTSET编码的集合ZIPLIST编码的列表、哈希表或有序集合
  • value的格式与编码对应请见 《第3章 对象》1.1 对象的定义 ;
  • 字符串对象的格式与示例:
  • 字符串对象可分为: 压缩字符串无压缩字符串 两种:

d164dcd88386f8ebcb8030d490fb4f88.png

7d61a2af4012cdee261e7ecef3dcdecf.png

列表与集合对象的格式:

b9572c97e48ad42545d8061824d85f48.png

哈希表对象的格式:

5ba3f401c8ab492147b5933b3af4c59b.png

0e4617ceca7932cc2c0990e329cf342f.png

有序集合对象的格式:

1721f7ad9821826fd844caba7c0ce7b7.png

f761acce1a5f7a5f04c54648d9a8517f.png

  • INTSET 编码集合的格式:将整数集合转换成字符串即可;
  • ZIPLIST编码的列表、哈希表或有序集合的格式:将压缩列表转换成一个字符串对象,然后再保存到 RDB 文件;


1.4 RDB 文件的示例


不包含任何键值对的 RDB 文件:

9b0d64d102635cbdeef704068d554add.png


2、AOF 持久化与 RDB 持久化的区别


  • AOF 持久化 :保存 Redis 服务器所执行的命令来记录数据库状态;
  • RDB 持久化 :保存数据库中的键值对来记录数据库状态不同;


3、 AOF 持久化


3.1 AOF 持久化的实现

  • AOF 持久化功能可分为:追加(append)、文件写入、文件同步(sync)三个步骤;
  • AOF 文件中的所有命令都以 Redis 命令请求协议的格式保存;
  • 当 AOF 持久化功能打开时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾:struct****redisServer{ //... //AOF 缓冲区 sds aof_buf; };
  • AOF 文件的写入与同步依赖事件循环 loop,每次循环主要有三个工作:处理文件事件 :负责接收客户端的命令请求,以及向客户端发送命令回复;处理时间事件 :执行需要定时运行的函数;flushAppendOnlyFile() :考虑是否将 aof_buf 中的内容追加到 AOF 文件中;
  • flushAppendOnlyFile()函数的行为由服务器配置的 appendfsync 选项的值决定,该值有三种不同的行为:

86b6f422aed9c45eca24edb90143fdf1.png

3.2 AOF 文件的载入与数据还原

服务器创建一个不带网络连接的伪客户(fake client),为客户端读入并执行 AOF 文件即可;

940d5e586ab2c3f69f12b5f58d93f7c7.jpg

3.3 AOF 重写

  • AOF 重写不需要对现有 AOF 文件进行任何读取、分析或写入操作,而是通过读取服务器当前数据库状态实现;
  • AOF 重写功能的实现原理: 从数据库读取键现在的值,然后用一条命令记录键值对,代替之前记录这个键值对的多条命令 ;
  • 为了避免执行命令时造成客户端输入缓冲区溢出,重写程序在处理列表、哈希表、集合、有序集合这四种键时,会检查元素数量,超过一定数量(64)时会使用多条命令记录这个键的情况;
  • 这个数量由常量 redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD 确定;

3.4 AOF 后台重写

AOF 重写需要解决2个问题:

  • 重写不能阻碍服务器处理客户端请求:使用 的进程 解决;
  • 的进程在 AOF 重写期间,父进程服务器对数据库状态进行修改,会使服务器当前状态与重写后 AOF 状态不一致:设置 AOF 重写缓冲区 解决;

Redis 将 AOF 重写程序放到 子进程 里执行:子进程进行 AOF 重写期间,服务器进程(父进程)可以继续处理命令请求;子进程带有服务器进程的数据副本,使用子进程而不是线程,避免使用锁的情况下保证数据安全;

d2bd5b45645741f0120085e429cb2cca.jpg

Redis 服务器设置一个 AOF 重写缓冲区 ,以保证:AOF 缓冲区的内容会定期被写入和同步到 AOF 文件,对现有 AOF 文件的处理工作如常进行;从创建子进程开始,服务器执行的所有命令都会被记录到 AOF 重写缓冲区里;

完成 AOF 重写工作后,向父进程发送一个信号,父进程接到信号后调用信号处理函数,执行以下工作:

将 AOF 重写缓冲区中的所有内容写入到新 AOF 文件,此时新 AOF 文件保存的数据库状态将与服务器当前的数据库状态一致;对新的 AOF 文件进行改名,原子地覆盖现有的 AOF 文件,完成新旧两个任务 AOF 文件的替换;

只有号处理函数执行时会对服务器进程(父进程)造成阻塞;

53438dc94e6295d1a01002981ebd5f30.jpg

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
28天前
|
存储 NoSQL 算法
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
44 0
|
28天前
|
NoSQL 数据处理 调度
【Redis深度专题】「踩坑技术提升」探索Redis 6.0为何必须启用多线程以提升性能与效率
【Redis深度专题】「踩坑技术提升」探索Redis 6.0为何必须启用多线程以提升性能与效率
192 0
|
2天前
|
存储 缓存 运维
软件体系结构 - 缓存技术(5)Redis Cluster
【4月更文挑战第20天】软件体系结构 - 缓存技术(5)Redis Cluster
136 10
|
7天前
|
存储 NoSQL Java
Redis奔溃了快看看有没开启持久化
Reis作为一个内存数据库,整个数据库状态都存储在内存里,如果在运行过程中发生崩溃,那整个数据库状态可就完全不见了,相当于整个服务器被初始化。Redis在这方面肯定有所作为,我们来看看它做了什么功夫~
121 0
Redis奔溃了快看看有没开启持久化
|
17天前
|
存储 NoSQL 算法
redis数据持久化
redis数据持久化
|
28天前
|
存储 NoSQL Redis
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)(三)
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)
29 0
|
28天前
|
NoSQL Java Redis
【Redis深度专题】「踩坑技术提升」一文教会你如何在支持Redis在低版本Jedis情况下兼容Redis的ACL机制
【Redis深度专题】「踩坑技术提升」一文教会你如何在支持Redis在低版本Jedis情况下兼容Redis的ACL机制
216 0
|
28天前
|
缓存 NoSQL Shell
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
146 0
|
28天前
|
存储 缓存 NoSQL
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)(一)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群功能分析)
315 0
|
3月前
|
监控 NoSQL Linux
【分布式】Redis的持久化方案解析
【1月更文挑战第25天】【分布式】Redis的持久化方案解析

热门文章

最新文章