设为首页 加入收藏

TOP

Redis内部数据结构详解之ziplist(四)
2014-11-24 00:44:28 来源: 作者: 【 】 浏览:41
Tags:Redis 内部 数据结构 详解 ziplist
ize(zl,curlen+reqlen+nextdiff); p = zl+offset; /* Apply memory move when necessary and update tail offset. */ if (p[0] != ZIP_END) { /* Subtract one because of the ZIP_END bytes */ //将原有从p-nextdiff开始全部向后偏移,余留出reqlen保存即将insert的数据 /** nextdiff = -4:原来p有5个字节来存储上个节点的长度,而现在只需要1个, 因此只需要将p+4后面的字节偏移到p+reqlen即可,这样就 只保留1个字节保存reqlen的长度了 nextdiff = 4: 原来p只有1个字节来存储上个节点的长度,现在需要5个, 那就将p-4后面的字节偏移到p+reqlen,这样p原来有1个字节 加上多偏移来的4个字节就可以保存reqlen的长度了 nextdiff = 0: 不需要考虑 */ memmove(p+reqlen,p-nextdiff,curlen-offset-1+nextdiff); /* Encode this entry's raw length in the next entry. */ zipPrevEncodeLength(p+reqlen,reqlen);//下个节点保存即将insert数据的所占字节数 /* Update offset for tail */ ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+reqlen); /* When the tail contains more than one entry, we need to take * "nextdiff" in account as well. Otherwise, a change in the * size of prevlen doesn't have an effect on the *tail* offset. */ // 有需要的话,将 nextdiff 也加上到 zltail 上 tail = zipEntry(p+reqlen); if (p[reqlen+tail.headersize+tail.len] != ZIP_END) { ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff); } } else { /* This element will be the new tail. */ // 更新 ziplist 的 zltail 属性,现在新添加节点为表尾节点 ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(p-zl); } /* When nextdiff != 0, the raw length of the next entry has changed, so * we need to cascade the update throughout the ziplist */ /** 如果nextdiff不等于0,说明现在的p+reqlen节点的长度变了,需要级联更新下个节点能否保存 p+reqlen节点的长度值 */ if (nextdiff != 0) { offset = p-zl; zl = __ziplistCascadeUpdate(zl,p+reqlen); p = zl+offset; } /* Write the entry */ p += zipPrevEncodeLength(p,prevlen);//填写保存上一个节点长度的字节数 p += zipEncodeLength(p,encoding,slen);//填写保存当前节点长度的字节数 if (ZIP_IS_STR(encoding)) {//保存当前节点的字符串 memcpy(p,s,slen); } else { zipSaveInteger(p,value,encoding);//整数 } ZIPLIST_INCR_LENGTH(zl,1);//length + 1 return zl; }

ziplist剩余的一些函数就不一一列举分析,理解上述三个函数,其余都很简单,关注这三个函数的重点是作者在realloc之后如何通过memmove保证后续节点的数据保持不变的,不得不说Redis的作者对ziplist的实现很让人佩服。

另外,推荐Redis黄健宏(huangz1990)的Redis设计与实现一书中有关于ziplist插入与删除节点的简单模拟实现。

九、小结

ziplist的最大的好处就是相比skiplist节约大量内存,但是在插入、删除、查询等操作上的时间复杂度与skiplist都是无法比拟的,当保存的数据比较少时,操作的时间自然可以接受,内存就是关键因素。

ziplist在Redis中主要用于Hash Table、List、Sorted Set数据类型小范围数据的存储,本文描述的ziplist的存储都是无序的,如何实现在Sorted Set中的有序存储待以后分析,无序变有序无疑又增加的时间复杂度。

总之,ziplist就是一种用时间换空间的策略。

最后感谢黄健宏(huangz1990)的Redis设计与实现及其他对Redis2.6源码的相关注释对我在研究Redis2.8源码方面的帮助。

由于本文其他有关ziplist的函数没有分析,包括本文内容有问题欢迎评论,有些代码我也不是特别的明白,谢谢。

首页 上一页 1 2 3 4 下一页 尾页 4/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇MongoDB之整库备份还原单表collec.. 下一篇DbVisualizerPersonal中文乱码问..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: