Redis RDB是什么

Redis rdb是Redis快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时,会重新加载dump.rdb文件的数据到内存当中恢复数据,另外搭建从库或者重建从库也需要拉取主库生成的rdb快照文件。rdb不仅应用于备份恢复和搭建从库,也广泛应用于离线key分析,例如:查找BigKey、HotKey、ColdKye或者Key的访问频率等。

我们可以通过输入info Persistence来查看Redis服务端记录的相关持久化状态的信息。

127.0.0.1:8888> info Persistence
#Persistence
loading:0                                                           #是否正在保存rdb文件
rdb_changes_since_last_save:356857684   #最后一次保存rdb文件之后改变的key的个数
rdb_bgsave_in_progress:0                              #后台是否正在保存rdb文件
rdb_last_save_time:1640573408                    #最后一次保存rdb文件的具体时间
rdb_last_bgsave_status:ok                              #最后一次保存rdb文件的状态,成功或者失败
rdb_last_bgsave_time_sec:0                          #最后一次保存rdb文件消耗的时间
rdb_current_bgsave_time_sec:-1                  #当前保存rdb文件所用的时间,"-1"表示后台没有正在rdb文件
rdb_last_cow_size:1064960                            #最后一次保存rdb文件的任务消耗的内存
.....

Redis RDB生成的触发条件

其实Redis生成rdb文件有时候是很重的操作,如果使用不当将会造成严重的生产故障。从生成rdb是否阻塞主线程来看,共有两种方式:阻塞式和非阻塞式。阻塞式:使用Redis主线程完成rdb文件的写入;非阻塞式:用Redis主线程fork的子线程完成rdb文件的写入,主线程只需要记录统计状态和指标。那么触发生成rdb文件的条件有哪些呢?请看下图。
![在这里插入图片描述]

(https://img-blog.csdnimg.cn/075c4f3a1dff4f1aadbcb63e2bef8a5a.png)
从上图可以看出有3个常用命令会触发生成rdb文件,并在生成rdb快照的过程中阻塞主线程,命令有:save、flushdb和shutdown,其中shutdown会在真正关机之前查看Redis服务是否开启rdb功能,开启才会阻塞写入rdb文件;非阻塞的方式有bgsave命令、serverCron定时任务及做从库时,做从库从master拉取rdb文件有两种选择,一种是主从落盘复制rdb和主从非落盘复制rdb。无论采用哪种方式最终调用的都是rdbSaveRio函数,rdbSaveRio函数是写rdb文件内容的主函数。

Redis RDB组织结构

Rdb文件是一个紧凑的二进制文件,整体上可分为三个区域:头信息区、数据区、尾信息区。

下图为使用系统命令od输出的Redis6.2.6的rdb文件内容,第一和第三行是用十六进制显示的 dump.rdb 文件的字节内容,这里每两个十六进制数对应了一个字节,而第二和第四行是 od 命令生成的每个字节所对应的 ASCII 字符,由于ASCII 字符只定义了128个字符,所以部分字符是无法识别的,例如0xfa、0xfe、0xc0等。

注意:rdb文件内容是非常紧凑的,不存在空格、换行的,那么是怎么分割信息呢?其实,在rdb每一部分之前都有一个类型字节,在Redis中称为opcodes,即操作符。

下表为RDB支持的部分操作符

16进制 10进制 简称 说明
0xFF 255 EOF rdb 文件结束符
0xFE 254 SELECTDB 标识文件中后续键值对所属的数据库编号
0xFD 253 EXPIRETIME redis过期时间,使用秒表示。
0xFC 252 EXPIRETIMEMS redis 过期时间,使用毫秒表示。
0xFB 251 RESIZEDB redis dbsize,描述 key 数目和设置了过期时间 key 数目
0xFA 250 AUX 辅助字段类型,可以存储任意的的 key-value 对
0xF9 249 FREQ 标识LFU访问频率信息
0xF8 248 IDLE 标识LRU空闲时间

RDB头信息区

RDB 文件头主要是描述信息,如 redis 版本、rdb 创建时间、内存大小等信息的内容,首先是魔数REDIS,后面的00009对应记录了 rdb 文件的版本,到目前为止Redis共有9个版本,各个版本差异说明请参考Redis RDB Version History,后面是redis版本6.2.6以及其他信息。AUX 指令即操作符:0xFA,描述 redis 属性,可存在多个 key-value 组合

RDB数据区

上图中数据区只有一个key,即key1:value1,实际rdb数据区是编码最复杂的区域,采用数十种不同编码方法。0xFE指定数据库编号,示例值 “00” 表示接下来是第 0 个库的数据。0xFB是RESIZEDB 指令,描述总的 key 个数以及有过期时间的 key 个数,总数有1个key,且有过期时间,0xFC 是EXPIRETIMEMS指令,key的过期时间,使用毫秒表示。0xF8是LFU frequency指令,key的访问频率,由于Redis 淘汰策略LRU和LFU共用一个数据结构,58同城线上Redis目前使用的淘汰策略是volatile-lru,所以通过解析rdb文件很容易获得key的访问时间,从而获得key的冷热程度,如果生产中采用scan或者key *等会造成访问时间被污染,从而失去参考意义。

RDB尾信息区

相对于头信息区和数据区,RDB尾信息区简单很多,只有文件描述符0xFF 和8 byte的CRC 64 校验码。

数据区编码详解

Redis rdb数据区内容主要为键值对,下图展示rdb保存key-value的各个元素的操作符和元素的顺序。

一些key没有过期策略就不会有EXPIERE_TIME元素,在Redis4.0以前rdb文件是不记录LFU和LRU的。另外由于LFU和LRU共用一个数据结构,所以两个功能只能启用一个。VALUE_TYPE为VALUE的类型,前面的xxx是opcodes的编码,具体编码可以参考下图,常见的值类型为:STRING、QUICKLIST、INTSET、SET、ZSET_ZIPLIST、ZSET_2、HASH_ZIPLIST、HASH等。

Redis数据类型/低层编码结构和值类型对应关系

数据类型 编码结构 值类型
OBJ_SRTRING(0) OBJ_ENCODING_RAW(0) RDB_TYPE_STRING(0)
OBJ_LIST(1) OBJ_ENCODING_QUICKLIST(9) RDB_TYPE_LIST_QUICKLIST(14)
OBJ_SET(2) OBJ_ENCODING_INTSET(6) RDB_TYPE_SET_INTSET(11)
OBJ_SET(2) OBJ_ENCODING_HT(2) RDB_TYPE_SET(2)
OBJ_ZSET(3) OBJ_ENCODING_ZIPLIST(5) RDB_TYPE_ZSET_ZIPLIST(12)
OBJ_ZSET(3) OBJ_ENCODING_SKIPLIST(7) RDB_TYPE_ZSET_2(5)
OBJ_HASH(4) OBJ_ENCODING_ZIPLIST(5) RDB_TYPE_HASH_ZIPLIST(13)
OBJ_HASH(4) OBJ_ENCODING_HT(2) RDB_TYPE_HASH(4)
OBJ_STREAM(6) RDB_TYPE_STREAM_LISTPACKS(15)

上表中这些字符串实际再Redis服务中都是用宏定义的,括号中即为该宏对应的值。

KEY在rdb文件中的保留形式

在Redis中key都可以看作字符串,在rdb文件中它的格式是这样的:

RDB字符串保存形式

其中LENGTH为了节省空间,采用了变长的格式,具体参考下表:

序号 第一个字节 第二个字节 第三个字节 第四个字节 第五个字节 第六个字节 第七个字节 第八个字节 表示范围 占用字节 其他说明
1 00xxxxxx - - - - - - - <64 1 sting格式
2 01xxxxxx xxxxxxxx - - - - - - <2^14 2 sting格式
3 10000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx - - - <2^32 5 sting格式
4 10000001 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx <2^56 8 sting格式
5 11000000 xxxxxxxx - - - - - - [-27,27-1] 2 int格式
6 11000001 xxxxxxxx xxxxxxxx - - - - - [-215,215-1] 3 int格式
7 11000010 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx - - - [-231,231-1] 5 int格式
8 11000011 LZF格式

另外RDB文件对字符串的保存有两种优化形式,一种是常识将字符串按照整型保存,一种是通过将字符串进行LZF压缩之后保存。

上表序号5-7是将字符串尝试用int保存的具体编码方式,下图为RDB将字符串转换为INT后的保存形式。

RDB字符串按整型保存形式


上表序号8是将字符串进行压缩保存的具体编码方式,首字节开头的两个bit仍然为11,后六个bit为000011。

RDB LZF保存形式

COMPRESS_LE表明压缩之后的长度,实际就是DATA的长度,ORIGINAL_LEN这个字段记录的是原始的数据记录长度。

Value在rdb文件中的保留形式

相对key在rdb的保存形式,value类型更多,其中字符串和key的保存相同,不再进行讨论。

1、list的保存

列表在Redis中编码为quicklist结构,从整体看是一个双向链表,但链表的每个节点在Redis中编码为ziplist结构在一块连续的内存中保存,并且保存时可以选择进行LZF压缩或者不压缩。下图为list在rdb中的保存结构。

list未压缩保存形式

list压缩保存形式

上图中QUICKLIST是保存的list的元素个数,如果list未压缩,ziplist1保存形式同字符串的保留形式;如果list压缩,LZF1保存形式同RDB LZF保存形式。

2、set的保存

set在Redis中有两种编码方式:一种是intset,一种是Hash。

使用intset的编码方式较为简单,直接使用字符串的方式,Hash的编码方式较为复杂,见下图

list hash保存形式

上图中字典大小实际记录的是list元素个数,字典键只记录了key,为啥没有value,因为list的元素都是单元素,value都为null,所以没有必要记录。

3、有序集合

zset在Redis中有两种编码方式:一种是ziplist,一种是skiplist。

使用ziplist的编码方式较为简单,直接使用字符串的方式,我重点介绍下skiplist的编码方式,见下图

zset skiplist保存形式

skiplist长度为zset元素数量,元素已字符串类型保存,元素分值为一个双精度浮点数类型(固定为8个字节)

4、hash类型

hash在Redis中有两种编码方式:一种是ziplist,一种是hash。

使用ziplist的编码方式较为简单,直接使用字符串的方式,我重点介绍下hash的编码方式,见下图

hash长度实际为hash的元素个数,键和值都是字符串的方式保存

总结

从以上的各类型保存形式可以发现,虽然数据类型很多,但是底层元素保存都遵循简单的字符串保留方式,所以重点总结了KEY在rdb文件中的保留形式

通过以上的介绍,希望大家能对RDB文件有个简单的了解,并最终指导开发RDB解析程序,为开发提供更加丰富的离线key分析产品。

相关链接:

从源码角度解析如何生成和解读RDB文件

redis rdb 文件格式详解

RDB分析源码

redis-rdb-tools地址

Redis RDB文件解析相关推荐

  1. Redis RDB文件的解析工具梳理(rdr/redis-rdb-tools)

    前言 目前关于Redis rdb文件解析的工具,目前了解到的主要有python写的 redis-rdb-tools 工具,和用golang写的 rdr 工具. https://github.com/s ...

  2. redis rdb文件恢复数据注意、踩坑

    redis rdb文件恢复数据注意.踩坑 我是docker安装的redis,拷贝dump.rdb文件到挂在的目录下后 重启docker redis,数据并没有被恢复.dump.rdb文件竟然被覆盖掉了 ...

  3. java读取rdb_剖析Redis RDB文件

    通过redis-cli中执行save或者bgsave可以得到RDB文件(文件名由配置文件中dbfilename指定,例如dbfilename "dump.rdb"),这个文件包含R ...

  4. 深入剖析Redis RDB持久化机制

    本文来自@凡趣科技 pesiwang同学的投稿分享,对Redis RDB文件持久化的内部实现进行了源码分析. 本文分析源码基于 Redis 2.4.7 stable 版本.下面是其文章原文: rdb是 ...

  5. redis快照文件dump.rdb解析工具--redis-rdb-tools

    解析Redis dump.rdb文件,分析内存并将数据导出到JSON Rdbtools是Redis的dump.rdb文件的解析器.解析器生成类似于xml sax解析器的事件,并且非常有效的内存明智. ...

  6. Redis RDB文件格式全解析

    RDB文件是Redis持久化的一种方式,Redis通过制定好的策略,按期将内存中的数据以镜像的形式转存到RDB文件中.那么RDB文件内部格式是什么样的呢,Redis又做了哪些工作让RDB能够更快的du ...

  7. redis源码剖析(十四)—— dump.rdb文件分析工具

    分析rdb文件的工具 安装 git clone https://github.com/sripathikrishnan/redis-rdb-tools.git sudo pip install --u ...

  8. 使用rdbtools工具分析redis备份RDB文件

    要分析redis的备份RDB文件,rdbtools是首选 安装rdbtools 先看下本机有没有装rdb whereis rdb 没有安装的话就要开始安装了,为因rdbtool是由python写的,所 ...

  9. redis之紧凑的rdb文件

    一.简介 rdb是redis持久化的一种方式,存储的是redis服务器在某个时刻的所有内存数据.在redis启动时可以直接解析加载到内存以恢复数据. 触发时机: save命令 bgsave命令 ser ...

最新文章

  1. Android RecyclerView添加Header头部
  2. 多视图立体匹配论文分享:BlendedMVS
  3. 北京大学信息科学技术学院招收2022级博士生
  4. 修改MD5加密 提高网站安全
  5. Mybatis框架中是如何获取到SQL语句的,让我们一起来模拟一下吧
  6. mysql命令查询语句
  7. mysql mysql常用的常用函数
  8. 【51nod - 1065】 最小正子段和( 前缀和排序 )
  9. 计算机网络(八)——web的工作原理
  10. python循环定义变量_Python变量和循环
  11. 我的java学习心得
  12. 微信小程序开发详细步骤
  13. VBA字典做数据有效性
  14. 操写一盒酥三字于盒上
  15. springboot小区公共停车位管理毕业设计-附源码201517
  16. 【源代码扫描工具】 -‪Checkmarx使用
  17. springboot 实现redis高并发抢票服务
  18. go语言学习笔记——框架与工具
  19. Vim插件之vim-autoformat
  20. c语言十六转十进制,C语言 · 十六进制转十进制

热门文章

  1. CAPL(vTESTStudio) - CAPL控制RS232继电器
  2. php中字母随机数,由数字字母生成php随机数的方法
  3. 又见人面桃花相映红!(2008-07-28 10:21:32| 分类: 心情故事)
  4. 小程序---获取view的高度
  5. 杭州内推 | 之江实验室招聘多模态算法实习生
  6. ClickHouse特性及底层存储原理
  7. 刘小凡的第一个CSON博客~
  8. HTC VIVE开发教程(五)
  9. [用python辅助学生中考与高考-4]:家长篇-中考科技特长生知多少如何通过Python来辅助学习数学?
  10. multiprocessing.freeze_support()介绍