2. 主从同步 (开启主从后,需要首先把master上的历史数据同步到slave,这时slave就会拉取master的rdb文件,然后解析加载rdb文件到内存)
rdb 保存了真实的redis数据,相当于mysql的innodb引擎的作用,可见其重要性非同一般。rdb也可以用来离线分析redis中数据分布情况。对于如此重要的文件,其中的数据存储格式我们当然要了如指掌,这样才能运筹帷幄,让可用性达到 4个9 (99.99%), 5个9(99.999%)
到目前为止,主要的rdb 版本是 v6 v7,从redis v3.2 版本开始使用 rdb v7,之前的redis v2.8 v3.0 使用的rdb版本都是rdb v6,文件的大致格式如下:
rdb v6
A 9 bytes magic "REDIS0006" (9字节的redis标记,其中末四位是rdb版本信息)
key-value pairs (redis 真实的数据,以key value 成对存储)
An EOF opcode (代表结束的标记)
CRC64 checksum (用于对整个文件完整性校验的字符串)
rdb v7
A 9 bytes magic "REDIS0007" (9字节的redis标记,其中末四位是rdb版本信息)
Info field 1 (整个rdb文件中为了保存一些额外扩展信息而设计)
Info field 2
...
Info field N
Info field end-of-fields
key-value pairs (redis真实数据,以key value 成对存储)
An EOF opcode (代表结束的标记)
CRC64 checksum (用于对整个文件完整性校验的字符串)
先来看看其中真实数据是如何存储的,也就是上面的 key-value pairs ,使用过json 的同学都知道这个保存非常简单,比如:
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
但这里并不是这样的结构,是一个连续的按字节存储的序列。如果连续存储,其中没有其他标记,如何区分 key 与 value的边界呢?换句话也就是如何知道key这个字串哪里结束,value从哪里开始呢?redis使用了提前记录字节长度的方式实现,也就是 key-len key value-len value 这种的形式,然后按对应长度读取字符。问题又来了,redis的key的最大长度是多少呢,value的最大长度是多少呢,好像也没有明确的限制,如果你不建议性能损失的话。
redis 使用了多字节的方式保存长度(1字节、2字节、5字节、9字节 ),根据不同长度使用不同的字节,但是这里面又会出现边界问题,当从rdb文件中读取2字节,如何区分这是1字节长度值+1字节key值,还是2字节的长度值呢?到了这里似乎更加迷茫,好像陷入了一个死循环,好像无解。
如果了解UTF8编码实现原理,你一定会有可行的解决方案。是的,我们先来看看一段redis源码,因为对一个系统最好的理解就是代码+注释,更何况redis中的注释也是相当的详细,基本一看就懂。
/* The current RDB version. When the format changes in a way that is no longer
* backward compatible this number gets incremented. */
#define RDB_VERSION 8
/* Defines related to the dump file format. To store 32 bits lengths for short
* keys requires a lot of space, so we check the most significant 2 bits of
* the first byte to interpreter the length:
*
* 00|XXXXXX => if the two MSB are 00 the len is the 6 bits of this byte
* 01|XXXXXX XXXXXXXX => 01, the len is 14 byes, 6 bits + 8 bits of next byte
* 10|000000 [32 bit integer] => A full 32 bit len in net byte order will follow
* 10|000001 [64 bit integer] => A full 64 bit len in net byte order will follow
* 11|OBKIND this means: specially encoded object will follow. The six bits
* number specify the kind of object that follows.
* See the RDB_ENC_* defines.
*
* Lengths up to 63 are stored using a single byte, most DB keys, and may
* values, will fit inside. */
#define RDB_6BITLEN 0
#define RDB_14BITLEN 1
#define RDB_32BITLEN 0x80
#define RDB_64BITLEN 0x81
#define RDB_ENCVAL 3
#define RDB_LENERR UINT64_MAX
/* When a length of a string object stored on disk has the first two bits
* set, the remaining six bits specify a special encoding for the object
* accordingly to the following defines: */
#define RDB_ENC_INT8 0 /* 8 bit signed integer */
#define RDB_ENC_INT16 1 /* 16 bit signed integer */
#define RDB_ENC_INT32 2 /* 32 bit signed integer */
#define RDB_ENC_LZF 3 /* string compressed with FASTLZ */
在上面的注释中有原作者的介绍,我在这里在按我自己的理解解释下:
1.
2.
3.
4.
未完待续