redisredissorted setredisskip list

基础

skip list

只是列举了部分我觉得比较好的。如果你看到了更牛逼的文章可以在下面评论出来。
如果你看完了还是不理解可以找下别的文章再理解下。

go 代码实现

跳转表结构

直接看原始论文中的配图吧。

指针数据e61725
// elementNode 数组指针,指向元素
type elementNode struct {
    next []*Element
}

// Element 跳转表数据结构
type Element struct {
    elementNode
    key   float64 // 用以排序和判断大小的关键字
    value interface{} // 定义元素,附加
}
skip list
指针数组skip listmaxLevelemaxLevellevellevel
type SkipList struct {
    elementNode
    maxLevel       int            // 最大深度
    length         int            // 长度,跳表中
    randSource     rand.Source    // 动态调节跳转表的长度
    probability    float64        // 概率
    probTable      []float64      // 存储位置,对应key
    mutex          sync.RWMutex   // 保证线程安全
    prevNodesCache []*elementNode // 缓存
}

含义解释:

elementNodeprobTablemutexprevNodesCachelengthmaxLevel

基本方法

const (
    // DefaultMaxLevel 默认skip list最大深度
    DefaultMaxLevel int = 18
    // DefaultProbability 默认的概率
    DefaultProbability float64 = 1 / math.E
)

// Key 获取key的值
func (e *Element) Key() float64 {
    return e.key
}

// Value 获取key的值
func (e *Element) Value() interface{} {
    return e.value
}


type SkipList struct {
    elementNode
    maxLevel       int            // 最大深度
    length         int            // 长度
    randSource     rand.Source    // 随机数种子,动态调节跳转表元素的层数
    probability    float64        // 概率
    probTable      []float64      // 存储位置,对应key
    mutex          sync.RWMutex   // 保证线程安全
    prevNodesCache []*elementNode // 缓存
}

// NewSkipList 新建跳转表
func NewSkipList() *SkipList {
    return NewWithMaxLevel(DefaultMaxLevel)
}

// ProbabilityTable 初始化 Probability Table
func ProbabilityTable(probability float64, maxLevel int) (table []float64) {
    for i := 1; i <= maxLevel; i++ {
        prob := math.Pow(probability, float64(i-1))
        table = append(table, prob)
    }
    return table
}

// NewWithMaxLevel 自定义maxLevel新建跳转表
func NewWithMaxLevel(maxLevel int) *SkipList {
    if maxLevel < 1 || maxLevel > DefaultMaxLevel {
        panic("invalid maxlevel")
    }

    return &SkipList{
        elementNode:    elementNode{next: make([]*Element, maxLevel)},
        prevNodesCache: make([]*elementNode, maxLevel),
        maxLevel:       maxLevel,
        randSource:     rand.New(rand.NewSource(time.Now().UnixNano())),
        probability:    DefaultProbability,
        probTable:      ProbabilityTable(DefaultProbability, maxLevel),
    }
}

// 随机计算最接近的
func (list *SkipList) randLevel() (level int) {
    r := float64(list.randSource.Int63()) / (1 << 63)
    level = 1
    for level < list.maxLevel && r < list.probTable[level] {
        level++ // 级别追加
    }

    return level
}

// SetProbability 设置新的概率,刷新概率表
func (list *SkipList) SetProbability(newProbability float64) {
    list.probability = newProbability
    list.probTable = ProbabilityTable(newProbability, list.maxLevel)
}

方法解释:

NewWithMaxLevelelementNodeprevNodesCacherandLevel

核心方法

跳表中元素的查找效率和AVL树差不多,那这个效率是怎么实现这么高的我们就在这里说一下。

首先我们看下论文中出现的查询的一个说明图,看最上面的那个图就好

12
6669912

其实用语言来表述不是很准确,那就直接看代码

// Get 获取key对应的值
func (list *SkipList) Get(key float64) *Element {
    list.mutex.Lock()
    defer list.mutex.Unlock() // 线程安全

    var prev *elementNode = &list.elementNode // 保存前置结点
    var next *Element

    for i := list.maxLevel - 1; i >= 0; i-- {
        next = prev.next[i] // 循环跳到下一个
        for next != nil && key > next.key {
            prev = &next.elementNode
            next = next.next[i]
        }
    }

    if next != nil && next.key == key { // 找到
        return next
    }

    return nil // 没有找到
}

自己理解的时候可以边在自己脑袋里面一步一步的执行这些代码,然后再结合图中的结构就很快就理解了。

接下来看跳表的插入和删除了。

func (list *SkipList) getPrevElementNodes(key float64) []*elementNode {
    var prev *elementNode = &list.elementNode // 保存前置结点
    var next *Element
    prevs := list.prevNodesCache // 缓冲集合
    for i := list.maxLevel - 1; i >= 0; i-- {
        next = prev.next[i] // 循环跳到下一个
        for next != nil && key > next.key {
            prev = &next.elementNode
            next = next.next[i]
        }
        prevs[i] = prev
    }
    return prevs
}

// Set 存储新的值
func (list *SkipList) Set(key float64, value interface{}) *Element {
    list.mutex.Lock()
    defer list.mutex.Unlock() // 线程安全

    var element *Element
    prevs := list.getPrevElementNodes(key)
    if element = prevs[0].next[0]; element != nil && key == element.key {
        element.value = value
        return element
    }

    element = &Element{
        elementNode: elementNode{next: make([]*Element, list.randLevel())},  // 通过概率随机指定一个 level 给新插入的元素,调用了前面出现的函数 randLevel
        key:         key,
        value:       value,
    }
    list.length++

    for i := range element.next { // 插入数据
        element.next[i] = prevs[i].next[i]
        prevs[i].next[i] = element // 记录位置
    }

    return element
}

// Remove 获取key对应的值
func (list *SkipList) Remove(key float64) *Element {
    list.mutex.Lock()
    defer list.mutex.Unlock() // 线程安全

    var element *Element
    prevs := list.getPrevElementNodes(key)
    if element = prevs[0].next[0]; element != nil && key == element.key {
        for k, v := range element.next {
            prevs[k].next[k] = v // 删除
        }

        list.length--
        return element
    }

    return nil
}
Set
var element *Element
    prevs := list.getPrevElementNodes(key)
    if element = prevs[0].next[0]; element != nil && key == element.key {
        element.value = value
        return element
        }
getPrevElementNodeskey12prevs
6699
Setprevs12prevs[0].next[0]
if element = prevs[0].next[0]; element != nil && key == element.key

另外一块比较核心的代码就是:

    for i := range element.next { // 插入数据
        element.next[i] = prevs[i].next[i]
        prevs[i].next[i] = element // 记录位置
    }
SkipListprevNodesCacheRemove
RemoveSet

go 源代码

package skipList

import (
    "math"
    "math/rand"
    "sync"
    "time"
)

const (
    // DefaultMaxLevel 默认skip list最大深度
    DefaultMaxLevel int = 18
    // DefaultProbability 默认的概率
    DefaultProbability float64 = 1 / math.E
)

// elementNode 数组指针,指向元素
type elementNode struct {
    next []*Element
}

// Element 跳转表数据结构
type Element struct {
    elementNode
    key   float64
    value interface{} // 定义元素
}

// Key 获取key的值
func (e *Element) Key() float64 {
    return e.key
}

// Value 获取key的值
func (e *Element) Value() interface{} {
    return e.value
}


type SkipList struct {
    elementNode
    maxLevel       int            // 最大深度
    length         int            // 长度
    randSource     rand.Source    // 动态调节跳转表的长度
    probability    float64        // 概率
    probTable      []float64      // 存储位置,对应key
    mutex          sync.RWMutex   // 保证线程安全
    prevNodesCache []*elementNode // 缓存
}

// NewSkipList 新建跳转表
func NewSkipList() *SkipList {
    return NewWithMaxLevel(DefaultMaxLevel)
}

// ProbabilityTable 初始化 Probability Table
func ProbabilityTable(probability float64, maxLevel int) (table []float64) {
    for i := 1; i <= maxLevel; i++ {
        prob := math.Pow(probability, float64(i-1))
        table = append(table, prob)
    }
    return table
}

// NewWithMaxLevel 自定义maxLevel新建跳转表
func NewWithMaxLevel(maxLevel int) *SkipList {
    if maxLevel < 1 || maxLevel > DefaultMaxLevel {
        panic("invalid maxlevel")
    }

    return &SkipList{
        elementNode:    elementNode{next: make([]*Element, maxLevel)},
        prevNodesCache: make([]*elementNode, maxLevel),
        maxLevel:       maxLevel,
        randSource:     rand.New(rand.NewSource(time.Now().UnixNano())),
        probability:    DefaultProbability,
        probTable:      ProbabilityTable(DefaultProbability, maxLevel),
    }
}

// 随机计算最接近的
func (list *SkipList) randLevel() (level int) {
    r := float64(list.randSource.Int63()) / (1 << 63)
    level = 1
    for level < list.maxLevel && r < list.probTable[level] {
        level++ // 级别追加
    }

    return level
}

// SetProbability 设置新的概率,刷新概率表
func (list *SkipList) SetProbability(newProbability float64) {
    list.probability = newProbability
    list.probTable = ProbabilityTable(newProbability, list.maxLevel)
}

// Set 存储新的值
func (list *SkipList) Set(key float64, value interface{}) *Element {
    list.mutex.Lock()
    defer list.mutex.Unlock() // 线程安全

    var element *Element
    prevs := list.getPrevElementNodes(key)
    if element = prevs[0].next[0]; element != nil && key == element.key {
        element.value = value
        return element
    }

    element = &Element{
        elementNode: elementNode{next: make([]*Element, list.randLevel())},
        key:         key,
        value:       value,
    }
    list.length++

    for i := range element.next { // 插入数据
        element.next[i] = prevs[i].next[i]
        prevs[i].next[i] = element // 记录位置
    }

    return element
}

// Get 获取key对应的值
func (list *SkipList) Get(key float64) *Element {
    list.mutex.Lock()
    defer list.mutex.Unlock() // 线程安全

    var prev *elementNode = &list.elementNode // 保存前置结点
    var next *Element

    for i := list.maxLevel - 1; i >= 0; i-- {
        next = prev.next[i] // 循环跳到下一个
        for next != nil && key > next.key {
            prev = &next.elementNode
            next = next.next[i]
        }
    }

    if next != nil && next.key == key { // 找到
        return next
    }

    return nil // 没有找到
}

// Remove 获取key对应的值
func (list *SkipList) Remove(key float64) *Element {
    list.mutex.Lock()
    defer list.mutex.Unlock() // 线程安全

    var element *Element
    prevs := list.getPrevElementNodes(key)
    if element = prevs[0].next[0]; element != nil && key == element.key {
        for k, v := range element.next {
            prevs[k].next[k] = v // 删除
        }

        list.length--
        return element
    }

    return nil
}

func (list *SkipList) getPrevElementNodes(key float64) []*elementNode {
    var prev *elementNode = &list.elementNode // 保存前置结点
    var next *Element
    prevs := list.prevNodesCache // 缓冲集合
    for i := list.maxLevel - 1; i >= 0; i-- {
        next = prev.next[i] // 循环跳到下一个
        for next != nil && key > next.key {
            prev = &next.elementNode
            next = next.next[i]
        }
        prevs[i] = prev
    }
    return prevs
}