Redis RDB文件格式全解析
RDB文件是Redis持久化的一种方式,Redis通过制定好的策略,按期将内存中的数据以镜像的形式转存到RDB文件中。那么RDB文件内部格式是什么样的呢,Redis又做了哪些工作让RDB能够更快的dump和加载呢,下面我们深入RDB文件,来看一看其内部结构。
首先我们来看一个RDB文件的概况图:
----------------------------# RDB文件是二进制的,所以并不存在回车换行来分隔一行一行. 52 45 44 49 53 # 以字符串 "REDIS" 开头 30 30 30 33 # RDB 的版本号,大端存储,比如左边这个表示版本号为0003 ---------------------------- FE 00 # FE = FE表示数据库编号,Redis支持多个库,以数字编号,这里00表示第0个数据库 ----------------------------# Key-Value 对存储开始了 FD $length-encoding # FD 表示过期时间,过期时间是用 length encoding 编码存储的,后面会讲到 $value-type # 1 个字节用于表示value的类型,比如set,hash,list,zset等 $string-encoded-key # Key 值,通过string encoding 编码,同样后面会讲到 $encoded-value # Value值,根据不同的Value类型采用不同的编码方式 ---------------------------- FC $length-encoding # FC 表示毫秒级的过期时间,后面的具体时间用length encoding编码存储 $value-type # 同上,也是一个字节的value类型 $string-encoded-key # 同样是以 string encoding 编码的 Key值 $encoded-value # 同样是以对应的数据类型编码的 Value 值 ---------------------------- $value-type # 下面是没有过期时间设置的 Key-Value对,为防止冲突,数据类型不会以 FD, FC, FE, FF 开头 $string-encoded-key $encoded-value ---------------------------- FE $length-encoding # 下一个库开始,库的编号用 length encoding 编码 ---------------------------- ... # 继续存储这个数据库的 Key-Value 对 FF ## FF:RDB文件结束的标志
下面我们对上面的内容进行详细讲解
Magic Number
第一行就不用讲了,REDIS字符串用于标识是Redis的RDB文件
版本号
用了4个字节存储版本号,以大端(big endian)方式存储和读取
数据库编号
以一个字节的0xFE开头,后面存储数据库的具体编号,数据库的编号是一个数字,通过 “Length Encoding” 方式编码存储,“Length Encoding” 我们后面会讲到。
Key-Value值对
值对包括下面四个部分
- Key 过期时间,这一项是可有可无的
- 一个字节表示value的类型
- Key的值,Key都是字符串,通过 “Redis String Encoding” 来保存
- Value的值,通过 “Redis Value Encoding” 来根据不同的数据类型做不同的存储
Key过期时间
过期时间由 0xFD 或 0xFC开头用于标识,分别表示秒级的过期时间和毫秒级的过期时间,后面的具体时间是一个UNIX时间戳,秒级或毫秒级的。具体时间戳的值通过“Redis Length Encoding” 编码存储。在导入RDB文件的过程中,会通过过期时间判断是否已过期并需要忽略。
Value类型
Value类型用一个字节进行存储,目前包括以下一些值:
- 0 = “String Encoding”
- 1 = “List Encoding”
- 2 = “Set Encoding”
- 3 = “Sorted Set Encoding”
- 4 = “Hash Encoding”
- 9 = “Zipmap Encoding”
- 10 = “Ziplist Encoding”
- 11 = “Intset Encoding”
- 12 = “Sorted Set in Ziplist Encoding”
Key
Key值就是简单的 “String Encoding” 编码,具体可以看后面的描述
Value
上面列举了Value的9种类型,实际上可以分为三大类
- type = 0, 简单字符串
- type 为 9, 10, 11 或 12, value字符串在读取出来后需要先解压
- type 为 1, 2, 3 或 4, value是字符串序列,这一系列的字符串用于构建list,set,hash 和 zset 结构
Length Encoding
上面说了很多 Length Encoding ,现在就为大家讲解。可能你会说,长度用一个int存储不就行了吗?但是,通常我们使用到的长度可能都并不大,一个int 4个字节是否有点浪费呢。所以Redis采用了变长编码的方法,将不同大小的数字编码成不同的长度。
- 首先在读取长度时,会读一个字节的数据,其中前两位用于进行变长编码的判断
- 如果前两位是 0 0,那么下面剩下的 6位就表示具体长度
- 如果前两位是 0 1,那么会再读取一个字节的数据,加上前面剩下的6位,共14位用于表示具体长度
- 如果前两位是 1 0,那么剩下的 6位就被废弃了,取而代之的是再读取后面的4 个字节用于表示具体长度
- 如果前两位是 1 1,那么下面的应该是一个特殊编码,剩下的 6位用于标识特殊编码的种类。特殊编码主要用于将数字存成字符串,或者编码后的字符串。具体见 “String Encoding”
这样做有什么好处呢,实际就是节约空间:
- 0 – 63的数字只需要一个字节进行存储
- 而64 – 16383 的数字只需要两个字节进行存储
- 16383 - 2^32 -1 的数字只需要用5个字节(1个字节的标识加4个字节的值)进行存储
String Encoding
Redis的 String Encoding 是二进制安全的,也就是说他没有任何特殊分隔符用于分隔各个值,你可以在里面存储任何东西。它就是一串字节码。
下面是 String Encoding 的三种类型
- 长度编码的字符串
- 数字替代字符串:8位,16位或者32位的数字
- LZF 压缩的字符串
长度编码字符串
长度编码字符串是最简单的一种类型,它由两部分组成,一部分是用 “Length Encoding” 编码的字符串长度,第二部分是具体的字节码。
数字替代字符串
上面说到过 Length Encoding 的特殊编码,就在这里用上了。所以数字替代字符串是以 1 1 开头的,然后读取这个字节剩下的6 位,根据不同的值标识不同的数字类型:
- 0 表示下面是一个8 位的数字
- 1 表示下面是一个16 位的数字
- 2 表示下面是一个32 位的数字
LZF压缩字符串
和数据替代字符串一样,它也是以1 1 开头的,然后剩下的6 位如果值为4,那么就表示它是一个压缩字符串。压缩字符串解析规则如下:
- 首先按 Length Encoding 规则读取压缩长度 clen
- 然后按 Length Encoding 规则读取非压缩长度
- 再读取第二个 clen
- 获取到上面的三个信息后,再通过LZF算法解码后面clen长度的字节码
List Encoding
Redis List 结构在RDB文件中的存储,是依次存储List中的各个元素的。其结构如下:
- 首先按 Length Encoding 读取这个List 的长度 size
- 然后读取 size个 String Encoding的值
- 然后再用这些读到的 size 个值重新构建 List就完成了
Set Encoding
Set结构和List结构一样,也是依次存储各个元素的
Sorted Set Encoding
todo
Hash Encoding
- 首先按 Length Encoding 读出hash 结构的大小 size
- 然后读取2×size 个 String Encoding的字符串(因为一个hash项包括key和value两项)
- 将上面读取到的2×size 个字符串解析为hash 和key 和 value
- 然后将上面的key value对存储到hash结构中
Zipmap Encoding
参见本站之前的文章:Redis zipmap内存布局分析
待续&欢迎投稿
Ziplist Encoding
Intset Encoding
Sorted Set as Ziplist Encoding
来源:RDB_File_Format.textile
from: http://blog.nosqlfan.com/html/3734.html
Redis RDB文件格式全解析相关推荐
- Redis RDB文件的解析工具梳理(rdr/redis-rdb-tools)
前言 目前关于Redis rdb文件解析的工具,目前了解到的主要有python写的 redis-rdb-tools 工具,和用golang写的 rdr 工具. https://github.com/s ...
- Redis RDB文件解析
Redis RDB是什么 Redis rdb是Redis快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时, ...
- 深入剖析Redis RDB持久化机制
本文来自@凡趣科技 pesiwang同学的投稿分享,对Redis RDB文件持久化的内部实现进行了源码分析. 本文分析源码基于 Redis 2.4.7 stable 版本.下面是其文章原文: rdb是 ...
- java春招面试冲刺系列:redis基础知识详细解析
目录 学习计划 学习笔记 百问 redis在什么情况下会变慢? 单线程的redis,如何知道要运行定时任务? 学习计划 Redis的介绍.优缺点.使用场景 Linux中的安装 常用命令 Redis各个 ...
- Redis RDB持久化
文章目录 一.持久化简介 二.数据快照RDB 1. save指令 2. RDB文件相关配置 验证save后数据保存在了rdb文件 验证重启服务后,程序会从rdb文件中恢复数据到内存 3. bgsave ...
- java读取rdb_剖析Redis RDB文件
通过redis-cli中执行save或者bgsave可以得到RDB文件(文件名由配置文件中dbfilename指定,例如dbfilename "dump.rdb"),这个文件包含R ...
- 2020年 Java 最常见200+ 面试题全解析:面试必备
Java 最常见200+ 面试题全解析:面试必备 如想了解更多更全面的Java必备内容可以阅读:所有JAVA必备知识点面试题文章目录: JAVA必备知识点面试题 序 言 在本篇文章开始之前,我想先来回 ...
- Python 常见的 170 道面试题全解析:2022 版
Python 常见的 170 道面试题全解析:2019 版 语言特性 1.谈谈对 Python 和其他语言的区别 答:Python 是一门语法简洁优美,功能强大无比,应用领域非常广泛,具有强大完备的第 ...
- python读取txt文件写入-Python读写txt文本文件的操作方法全解析
一.文件的打开和创建 >>> f = open('/tmp/test.txt') >>> f.read() 'hello python! hello world! ...
最新文章
- des加密算法python代码_python des加密算法代码(pydes模块加密)
- 复平面中的点集预备知识
- 1核1g服务器php,虚拟主机1核1g什么意思
- MySQL数据库规范及解读
- ctf 改变图片高度_CTF中.htaccess文件的利用
- jQuery WeUI学习笔记一
- 印象笔记 离线版_印象笔记pc版离线
- NPN和PNP三极管搭建推挽电路实验
- 流氓软件驱动精灵 强制锁定浏览器主页
- 儿童自行车品牌推荐全球十大儿童山地自行车品牌排行榜
- c语言硬币大小,C语言抛硬币
- Go语言编程笔记16:存储数据
- 微风:AI新手入门学习教程
- 佳人何处有,明月寄相思
- 新手入门电脑和S7 200Smart PLC 的自由口通信
- cortana小娜不能文字搜索,只能用语音搜索【修复教程】
- 【dva】dva使用与实现(四)
- 【LeetCode刷题】二月汇总篇
- 洛谷 P1862 输油管道问题
- 网络安全基础知识篇----nginx安装
热门文章
- java获取当前方法
- 孙正义看未来30年:投资趋势,永远不会错
- 基于R的信用评分卡模型解析
- 这年头,老赖没得混了!大数据式追债,你见过吗?
- Java Review - 并发编程_锁的分类
- Linux启动多个Oracle实例
- C++五子棋(二)——游戏界面与棋子渲染
- 为什么需要使用到多线程
- 什么是html的编码方式,HTML网页中“上”是什么编码方式啊?网页中&# 爱问知识人...
- pc双网卡实现路由转发_route命令如何使用?如何利用route命令实现内外网切换?...