Redis中五大数据结构的底层实现( 二 )


//值
union{
void *val;
uint64_tu64;
int64_ts64;
}v;
 
//指向下一个哈希表节点,形成链表
struct dictEntry *next;
}dictEntry
 
key 用来保存键,val 属性用来保存值,值可以是一个指针,也可以是uint64_t整数,也可以是int64_t整数 。
 
注意这里还有一个指向下一个哈希表节点的指针,我们知道哈希表最大的问题是存在哈希冲突,如何解决哈希冲突,有开放地址法和链地址法 。这里采用的便是链地址法,通过next这个指针可以将多个哈希值相同的键值对连接在一起,用来解决哈希冲突 。
 

Redis中五大数据结构的底层实现

文章插图
 
 
五、跳跃表
 
1、概述
 
跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的 。跳跃表是一种随机化的数据,跳跃表以有序的方式在层次化的链表中保存元素,效率和平衡树媲美 ——查找、删除、添加等操作都可以在对数期望时间下完成,并且比起平衡树来说,跳跃表的实现要简单直观得多 。
 
Redis 只在两个地方用到了跳跃表,一个是实现有序集合键,另外一个是在集群节点中用作内部数据结构 。
 
Redis中跳跃表节点定义如下:
 
typedef struct zskiplistNode {
//层
struct zskiplistLevel{
//前进指针
struct zskiplistNode *forward;
//跨度
unsigned int span;
}level[];
 
//后退指针
struct zskiplistNode *backward;
//分值
double score;
//成员对象
robj *obj;
 
} zskiplistNode
 
多个跳跃表节点构成一个跳跃表:
 
typedef struct zskiplist{
//表头节点和表尾节点
structz skiplistNode *header, *tail;
//表中节点的数量
unsigned long length;
//表中层数最大的节点的层数
int level;
 
}zskiplist;
 
  • header和tail指针分别指向跳跃表的表头和表尾节点;
  • length属性记录节点的数量;
  • level属性记录层数最高的几点的层数量;
  • 下图分别展示了完整的跳跃表和单个节点的详细结构图:
 
Redis中五大数据结构的底层实现

文章插图
 
 
2、特性
 
跳表具有如下性质:
 
  • 由很多层结构组成
  • 每一层都是一个有序的链表
  • 最底层(Level 1)的链表包含所有元素
  • 如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现 。
  • 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素 。
 
六、整数集合
 
1、概述
 
《Redis 设计与实现》 中这样定义整数集合:“整数集合是集合建的底层实现之一,当一个集合中只包含整数,且这个集合中的元素数量不多时,redis就会使用整数集合intset作为集合的底层实现 。”
 
我们可以这样理解整数集合,他其实就是一个特殊的集合,里面存储的数据只能够是整数,并且数据量不能过大 。
 
typedef struct intset{
//编码方式
uint32_t encoding;
//集合包含的元素数量
uint32_t length;
//保存元素的数组
int8_t contents[];
 
}intset;
 
我们观察一下一个完成的整数集合结构图:
 
Redis中五大数据结构的底层实现

文章插图
 
 
  • encoding:用于定义整数集合的编码方式
  • length:用于记录整数集合中变量的数量
  • contents:用于保存元素的数组,虽然我们在数据结构图中看到,intset将数组定义为int8_t,但实际上数组保存的元素类型取决于encoding
 
2、特性
 
  • 整数集合是集合建的底层实现之一
  • 整数集合的底层实现为数组,这个数组以有序,无重复的范式保存集合元素,在有需要时,程序会根据新添加的元素类型改变这个数组的类型
  • 升级操作为整数集合带来了操作上的灵活性,并且尽可能地节约了内存2
  • 整数集合只支持升级操作,不支持降级操作
 
七、压缩列表
 
1、概述


推荐阅读