问题描述
问题:Redis中哈希对象有两种编码方式,分别是ziplist、hashtable方式。哈希对象,总得体现哈希算法,使得基本操作达到O(1)的效率。hashtable编码方式使用字典,也即是Java中hashMap的方式,这个我可以理解。但是,ziplist方式所有元素都是紧挨的,它是怎么实现hash,并使得查询等操作有O(1)的时间效率的呢?
分析:
让我们从方法调用开始分析。我们都知道,获取哈希对象中某个元素的命令是“HGET”,当哈希对象的编码方式是ziplist时,它的执行过程如下:
- 首先调用ziplistFind函数,在压缩列表中查找指定键对应的节点。
- 然后调用ziplistNext函数,将指针移动到键节点旁边的值节点,最后返回值节点。
从HGET命令在ziplist编码下的执行过程可以看出,问题的关键在ziplistFind方法中。
ziplistFind方法在Redis源码的src/ziplist.c中:
/* 源码注释来自黄键宏先生的github Redis源码注释版本仓库:https://github.com/huangz1990/redis-3.0-annotated
* Find pointer to the entry equal to the specified entry.
*
* 寻找节点值和 vstr 相等的列表节点,并返回该节点的指针。
*
* Skip 'skip' entries between every comparison.
*
* 每次比对之前都跳过 skip 个节点。
*
* Returns NULL when the field could not be found.
*
* 如果找不到相应的节点,则返回 NULL 。
*
* T = O(N^2)
*/
unsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip) {
int skipcnt = 0;
unsigned