redis跳表——zset的底层实现
redis中有序集合的实现采用了一种数据结构——跳跃表。跳跃表是有序单链表的一种改进,其查询、插入、删除也是O(logN)的时间复杂度。
zset的两种实现方式
-
ziplist(压缩链表):满足以下两个条件的时候
- 元素数量少于128的时候
- 每个元素的长度小于64字节
-
skiplist(跳跃链表):不满足上述两个条件就会使用跳表,具体来说是组合了map和skiplist
- map用来存储member到score的映射,这样就可以在O(1)时间内找到member对应的分数
- skiplist按从小到大的顺序存储分数
- skiplist每个元素的值都是[score,value]对
skiplist原理
上图用a,b,c,d,e五种有序链表说明了跳跃表的motivation.
- [a]单链表:查询时间复杂度O(n)7
- [b]level-2单链表:每隔一个节点为一个level-2节点,每个level-2节点有2个后继指针,分别指向单链表中的下一个节点和下一个level-2节点。查询时间复杂度为O(n/2)
- [c]level-3单链表:每隔一个节点为一个level-2节点,每隔4个节点为一个level-3节点,查询时间复杂度O(n/4)
- [d]指数式单链表:每隔一个节点为一个level-2节点,每隔4个节点为一个level-3节点,每隔8个节点为一个level-4节点(每2^i个节点的level为i+1),查询时间复杂度为O(log2N)
- [e]跳跃表:各个level的节点个数同指数式单链表,但出现的位置随机,查询复杂度是O(logN)
redis选择跳跃表而非红黑树作为有序集合实现方式的原因并非是基于并发上的考虑,因为redis是单线程的,选用跳跃表的原因仅仅是因为跳跃表的实现相较于红黑树更加简洁。