《Redis设计与实现》读书笔记(十五) ——Redis RDB文件结构与文件分析

《Redis设计与实现》读书笔记(十五) ——Redis RDB文件结构与文件分析

(原创内容,转载请注明来源,谢谢)

一、RDB文件结构

1、结构概述

rdb文件结构如下图所示:

1)第一个部分,是‘REDIS’五个字组成的字符串常量,长度5字节,用于文件在载入之前快速判断载入的文件是否是rdb文件。

2)db_version属性长度4字节,值是字符串表示的整数,记录rdb的版本号,例如如果该rdb文件是第六版,则属性值为“0006”。

3)databases包含0个或任意个数据库,以及数据库中的键值对数据:如果服务器状态是空,没有数据,则此部分也是空,长度0字节;如果服务器有内容,则此部分不空,长度根据数据库的键值对数量决定。

4)第四部分,是EOF常量,长度1字节,表示rdb文件正文结束,键值对载入完毕。

5)check_sum属性是一个8字节长的无符号整数,保存一个校验和,该值是程序通过前四部分计算得到的结果,服务器载入数据后,会将载入的内容计算校验和,并于check_sum的值进行比较,以此检查rdb文件是否有出错或损坏。

redis服务器所有数据库都是空的情况,rdb文件结构如下图所示:

2、databases部分

rdb文件的databases部分保存任意个非空数据库,例如有两个非空数据库的情况如下图所示:

每个database内部的结构如下图所示:

1)SELECTDB是一个1字节长的常量,标记接下来要读入的是数据库的编号。

2)db_number是数据库编号,长度是1、2或5字节。程序读入此属性后,会调用select命令进行数据库间的切换。

3)key_value_pairs保存数据库键值对数据,包含键值对的过期时间。该部分长度根据键值对的数量、类型、内容以及是否有过期时间等条件而变化。

当0、3两个数据库有键值对数据时,rdb文件结构如下图所示:

3、key_value_pairs部分

该部分主要保存键值对及其过期时间信息。结构如下图所示:

1)TYPE是一个常量,记录键值对的类型,占1字节空间,类型即redis的基础数据编码,如string、list、set、hash、ziplist、intset等。

2)key是字符串对象,保存的是键的对象。

3)value对象根据type变化,保存的是值的对象。

下面两个是过期时间相关,如果没有对键值对设定过期时间,则没有相应的值。

4)EXPIRETIME_MS,是一个1字节的常量,告诉程序下一个内容是unix的毫秒的时间,用于表示其后键值对的过期时间。

5)ms,毫秒为单位的unix时间戳,8字节长的带符号整数,表示后面键值对的过期时间。

4、value部分

不同的redis对象会用不同的方法保存。

1)字符串对象

如果小于20字节、或者字符串对象是整数,则保存长度和字符串本身;如果超过20字节,则保存压缩前长度、压缩后长度、压缩值、以及一个标签用于标记该字符串是被压缩的,压缩算法采用LZF算法。

编码方式为int或raw。

无压缩字符串如下:

压缩字符串如下:

2)列表对象

列表对象保存方式,首先一个内存空间表示列表元素个数,接着连续两个内存空间,前一个放的是单个元素的长度,第二个空间放的是元素的值。如果有多个元素,则以长度、值、长度、值的方式排列。

默认编码方式是linkedlist。

列表如下:

如果采用ziplist,则会先将整个压缩列表转成字符串对象,再存入rdb文件。

3)集合对象

集合对象的保存方式,首先一个空间保存集合的个数,接着若干空间分别保存每个元素的长度与值。

默认编码方式为hashtable。

集合如下:

如果集合采用intset方式编码,则rdb保存时,会先将整数转成字符串对象,再进行保存。读入的时候,根据type转成整数,再存入内存。

4)哈希对象

哈希对象的保存方式,首先一个空间保存哈希键值对个数,接着按照键长度、键内容、值长度、值内容的方式排列。

默认编码方式为hashtable。

哈希如下:

5)有序集合对象

有序集合对象的保存方式,首先一个空间保存有序集合元素个数,接着按照元素长度、元素内容、分数长度、分数内容的方式排列。

默认编码方式为skiplist+hashtable。

有序集合如下:

二、RDB文件分析

在linux环境下,用od命令,可以将rdb文件转存成可以查看的形式,例如:

od –c dump.rdb,将rdb文件转成ascii的形式打开。

1、不包含键值对的rdb文件

打开一个不包含键值对的rdb文件,里面也有一些默认的数据,包括:

“REDIS”字符串、四字节版本号、一字节eof常量、八字节校验和。

2、包含键值对的rdb文件

除了上述默认内容,还会有键值对的信息。如果键值对包含过期信息,则过期信息也会存在其中。如下图所示:

3、其他

redis自带rdb文件检查工具redis-check-dump。另外,od –cx dump.rdb,可以将结果采用16进制的形式展示,更加直观。如下图所示:

三、总结

1、rdb用于保存和还原redis服务器所有数据库中的键值对数据。

2、save由服务器进程直接保存,会阻塞,save期间无法处理客户端的命令;bgsave会创建一个子进程进行保存,期间可以继续处理客户端命令。执行bgsave期间如果有save或bgsave命令,则服务器拒绝;如果有bgwriteaof,则会延迟到bgsave命令执行完毕后执行。如果在执行bgwriteaof命令期间,bgsave命令会被拒绝。

3、redis服务器没有专门的载入rdb文件命令,每次服务器开机,自动检查是否有rdb文件,有的话自动载入。但是如果服务器配置中开启aof,则会载入aof,rdb文件无效。

4、设置redis的save选项,包括改动次数和时间间隔,多个条件只要有一个满足,服务器就会自动执行bgsave(满足第二点执行条件为前提)。改动包括对键的增删改。

5、rdb文件是压缩成二进制的文件,不同类型的键值对,redis会用不同方式保存,并且可以在linux系统中,采用od –cx 文件名的方式,用十六进制ascii编码方式查看rdb文件。目前redis采用的是第六版的rdb文件

——written by linhxx 2017.09.04

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-09-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏史上最简单的Spring Cloud教程

Openresty最佳案例 | 第2篇:Lua入门

什么是lua Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能...

4259
来自专栏Young Dreamer

Vue Router的懒加载路径

1191
来自专栏积累沉淀

storm的数据流组

数据流组 设计一个拓扑时,你要做的最重要的事情之一就是定义如何在各组件之间交换数据(数据流是如何被bolts消费的)。一个数据流组指定了每个bolt会消费哪...

2079
来自专栏Rgc

Flask与WSGI

刚开始接触到python及Flask框架时,总是会听到 wsgi等等相关的名词,以及 项目部署时会用到nginx+gunicorn等等,但是对于一个请求从 ni...

551
来自专栏mySoul

脚本化HTTP 取得响应 指定请求

下面将会说明在没有导致web浏览器重新加载任何窗口或者窗体的情况下,脚本实现web浏览器和服务器之间的通信。

924
来自专栏编程

autoload自动加载机制使用

在PHP开发过程中,如果希望从外部引入一个class,通常会使用include和require方法,去把定义这个class的文件包含进来,但是这样可能会使得在...

18910
来自专栏IMWeb前端团队

让fetch也可以timeout

本文作者:IMWeb zzbozheng 原文出处:IMWeb社区 未经同意,禁止转载 原生的HTML5 API fetch并不支持timeout属性...

2035
来自专栏抠抠空间

RESTful规范

1640
来自专栏python 实践经验

python 语法基础之字符集编码

Python初学者编码实践中经常遇到encode error,decode error。

3165
来自专栏有困难要上,没有困难创造困难也要上!

Python运行时动态查看进程内部信息

2795

扫码关注云+社区