文章目录
前言
上一篇文章笔者写了关于HDFS使用SkipList跳表的结构来加速Snapshot的diff比较过程,然后加速HDFS大Snapshot删除的过程(此部分文章可阅读上篇博文:聊聊HDFS删除Snapshot行为导致的NameNode crash)。本文笔者想继续聊聊这个跳表结构,简单说就是构造多链表层级结构,利用(数据存储空间)空间来换取(数据查找效率)时间的一个数据结构用例。
SkipList样例结构
为了方便SkipList的样例讲解,本文设计实现的简单SkipList的内部结构如下所示,以插入时间排序的链表。
跳表的简单实现,通过维护多层级链表的形式,加速节点的查询,通过内存中维护更多
的节点信息来换取查询的速度。
跳表结构如下所示,基于time-based排序的链表结构.
level 4: head----------------------------------s9->NULL
level 3: head----------------->s5--------------s9->NULL
level 2: head------s2--------->s5--------------s9->NULL
level 1: head->s1->s2->s3->s4->s5->s6->s7->s8->s9->NULL
在以上每个数据项内,可以包含实际对象的信息。
SkipList样例代码简单实现
在笔者对SkipList的代码实现中,总共包含3个类:
- SkipListNode:跳表内部节点实例
- DiffSkipList:跳表类,供外部调用使用的类
- TestSkipListNode:对于跳表类的功能测试类
此样例的实现思路参考了HDFS Snapshot删除行为中实现的跳表结构类DiffListBySkipList。
下面依次是实现代码:
SkipListNode.java
/**
* 跳表内部节点实现.
*/
public class SkipListNode {
/** 跳表节点id */
private int id;
/** 节点所代表的值 */
private int value;
/**
* 跳表节点对应不同level层级的下一节点信息
*/
private SkipDiff[] skipDiff;
public SkipListNode(int id, int value, int level) {
super();
this.id = id;
this.value = value;
this.skipDiff = new SkipDiff[level];
}
public void setSkipDiff(int level, SkipDiff diff) {
this.skipDiff[level - 1] = diff;
}
public void setNextNode(int level, SkipListNode nextNode) {
// 计算当前节点和下一节点的状态差值
int diff = (nextNode == null) ? -1 : Math.abs(nextNode.value - this.value);
SkipDiff skipDiff = new SkipDiff(diff, nextNode);
// 设置level级别对应的下一节点值
setSkipDiff(level, skipDiff);
}
public int getId() {
return this.id;
}
public int getValue() {
return this.value;
}
public SkipListNode getNextNode(int level) {
return this.skipDiff[level - 1] == null ? null
: this.skipDiff[level - 1].nextNode;
}
public int getDiff(int level) {
return this.skipDiff[level - 1] == null ? -1