Redis中hashtable内部实现的细节
针对上图,对于四个知识点进行讲解,本文参考了其他博客的文章,有的知识点需要看详细的博客,我会列出博客的链接。上面四个知识点应该涵盖redis涉及到的所有细节,如何还有,请大家多多提出,一起探讨。。。
博客链接:http://www.hoterran.info/redis_dict
一、hashtable的内存结构
总结就是:两个数组链表的数据结构,请看网友画的图:
问题提出:
1、dict 包含了2个dictht hashtable ht[0], ht[1],为什么要包含两个hashtable?
这是做的目的扩容即rehash所带来的性能问题,采取了平稳的扩容机制,而不像java中的hashmap扩容是一次性的rehash,这样带来了很大的性能问题
2、为什么第二个hashtable是第一个hashtable的两倍呢?
3、为什么要rehash?
随着key不断的添加,bucket下的单链表越来越长,查找、删除效率越来越低,需要对ht进行expand,增加bucket个数,让链表的长度减少。bucket数量的增多,原有bucket的key需要迁移到新的bucket上,于是有了rehash的这个过程
4、什么时候rehash?
对于数据是如何添加、修改、删除、查找请看第四部分
二、zipmap
问题:
1、为什么使用zipmap?
保证在hashtable刚创建以及元素较少时,用更少的内存来存储,同时对查询的效率也不会受太大的影响,
而当hashtable元素不超过254个元素就使用,zipmap存储否则就转向hashtable存储。
先来看一下zipmap提供的和存储相关的3个API:
- zipmapNew:创建一个zipmap字符串。zipmap创建时只有2个字节,后面会随着set和delete操作动态扩展和收缩。
- zipmapSet: 加入新的key/value或者修改zipmap中已有key对应的value。
- zipmapDel:从zipmap中删除key/value。
下面给出一段伪代码并分析其内存布局的变化,如下图:
- zipmapNew();
- zipmapSet(key1,value1);
- zipmapSet(key2,value2);
- zipmapSet(key1,value3);
- zipmapDel(key2);
- zipmapSet(key1,value4);