类型介绍
zipmap也是redis的存储类型之一,这里面是sting->string的map结构,之所以出现这种形式的类型,主要是为了节省内存空间,采用的序列内存的方式,这种方式的一个问题就是查找的时候不是O(1)的复杂度,而是O(N)的时间复杂度,因此,它的目的是为了应付小规模的数据的,大规模的数据会过渡到hash表结构,这样应该是为了实现效率与空间的一种平衡;
内存格式为:
zmlen–len–“foo”–len–free–“bar”–len–“hello”–len–free–“world”
zmlen,是指zipmap中包含的entry数目,大于254的话,就不起作用了,当做标记开头;
len,是指key的长度,小于254的话占据一个字节,超过的话,后面跟着4个字节来表示长度;
free,空位,一般不会超过4个
代码分析
变量
ZIPMAP_BIGLEN, zipmap的最大长度
ZIPMAP_END, zipmap的结束符
ZIPMAP_VALUE_MAX_FREE, zipmap的free部分最大长度
函数
zipmapNew,新建一个zipmap;
unsigned char *zipmapNew(void) {
unsigned char *zm = zmalloc(2);
zm[0] = 0; /* Length */
zm[1] = ZIPMAP_END; //结尾标志,0XFF
return zm;
}
zipmapDecodeLength,zipmap解码长度信息;
static unsigned int zipmapDecodeLength(unsigned char *p) {
unsigned int len = *p;
if (len < ZIPMAP_BIGLEN) return len; //如果长度小于254,无需编码
memcpy(&len,p+1,sizeof(unsigned int)); //长度超过255,获取p指针的后面的4个字节的数据
memrev32ifbe(&len); //获取该4个自己对应的数据,需要根据大小端判断,来解析长度信息
return len;
}
zipmapEncodeLength,zipmap编码长度信息;
static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {
if (p == NULL) {
return ZIPMAP_LEN_BYTES(len); //如果p为NULL,则单纯返回该长度需要的内存字节数目
} else {
if (len < ZIPMAP_BIGLEN) {
p[0] = len; //如果小于254,那么无需编码,直接复制给当前字节
return 1; //主需要一个字节来保存长度信息
} else {
p[0] = ZIPMAP_BIGLEN;
memcpy(p+1,&len,sizeof(len));
memrev32ifbe(p+1); //需要硬编码到内存
return 1+sizeof(len); //需要5个字节来保存长度信息
}
}
}
zipmapLookupRaw,zipmap的查找过程;
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {
unsigned