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

相关文章

来自专栏C语言及其他语言

【每日一题】1452:[蓝桥杯][历届试题]网络寻路

题目描述 X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点...

2648
来自专栏Aloys的开发之路

Hibernate与autoCommit

JDBC 的autoCommit属性 对于每一个 JDBC connection,都有一个autoCommit属性,只有执行commit后,该connectio...

1718
来自专栏python3

python标准库--logging模块

它们的值为0-50(也可以自定义级别),这些级别的用处是,先将自己的日志定一个级别,logging模块发出的信息级别高于定义的级别,将在标准输出(屏幕)显示出来...

641
来自专栏HappenLee的技术杂谈

Python读取大文件的"坑“与内存占用检测

随手搜索python读写文件的教程,很经常看到read()与readlines()这对函数。所以我们会常常看到如下代码:

642
来自专栏柠檬先生

hibernate-笔记

什么是 hibernate 框架     1.hibernate 框架应用在 javaee 三次结构中 dao 层框架     2.在dao 层里面对数据库做c...

1827
来自专栏转载gongluck的CSDN博客

UNPv13:#第3章#套接字编程简介

IPv4套接字地址结构 POSIX规范只要求3个字段:sin_family、sin_addr和sin_port。 #include <netinet/in.h>...

3115
来自专栏java 成神之路

Java 序列化 之 Serializable

34413
来自专栏owent

[libiniloader] Project

Github地址: https://github.com/owt5008137/libiniloader

621
来自专栏xcywt

关于 getsockname、getpeername和gethostname、gethostbyname

一、gethostname,gethostbyname的用法 这两个函数可以用来获取主机的信息。 gethostname:获取主机的名字 gethostbyna...

1765
来自专栏开发 & 算法杂谈

Redis源码阅读之rdb.c

REDIS_RDB_ENC_LZF |compressed_len | original_len | compressed_string

754

扫描关注云+社区