《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 条评论
登录 后参与评论

相关文章

来自专栏Java技术栈

多线程通信的三大法器,你真的会用吗?

wait, notify, notifyAll 是多线程之间通信最重要的 3 个方法,今天,栈长给大家普及一下它们的知识要点及应用实战。

713
来自专栏瓜大三哥

HLS Lesson16-数组优化:数组分割

数组可以通过resource这个directive精确指定当前使用的memory。比如是分布式RAM还是Block RAM,采用单端口或者双端口。提高数据的吞吐...

23910
来自专栏Python小屋

Python快速计算Fibonacci数列中第n项的方法

from time import time from functools import lru_cache def fibo1(n): '''递归法''' ...

3097
来自专栏猿人谷

unix共享内存要点

共享内存优点:     1.在进程之间不通过内核传递数据,即不通过系统调用拷贝数据,达到快速,高效的数据传输。     2.随内核持续     *nix的共享内...

1755
来自专栏Python小白进阶之旅

ConfigParser:Python中对于ini格式的配置文件的使用

文章链接: http://note.youdao.com/noteshare?id=dfec323b2c6509d7189453ec730b3870&sub=7...

1062
来自专栏Web项目聚集地

你真的懂「类的加载机制」吗?

高广超 :多年一线互联网研发与架构设计经验,擅长设计与落地高可用、高性能互联网架构。目前就职于美团网,负责核心业务研发工作。本文首发在 高广超的简书博客,欢迎点...

1023
来自专栏mathor

线程的基本概念

1014
来自专栏企鹅号快讯

PHP高级特性之反射

反射-Reflection 面向对象编程中对象被赋予了自省的能力,而这个自省的过程就是反射。 反射,直观理解就是根据到达地找到出发地和来源。比如,一个光秃秃的对...

1979
来自专栏猿人谷

unix共享内存要点

共享内存优点:     1.在进程之间不通过内核传递数据,即不通过系统调用拷贝数据,达到快速,高效的数据传输。     2.随内核持续     *nix的共享内...

17410
来自专栏py+selenium

python如何将一个多位数数值转换为列表类型

914

扫码关注云+社区