《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