定义
Redis中的Ziplist是一种压缩列表(compact list)数据结构,用于代替双端链表、哈希表等常规数据结构。它可以在内存占用较小的情况下支持随机访问,适合存储长度小且元素数量少的列表。
Ziplist将多个节点连续存储在一个紧凑的可重复利用的内存区域中,相比于双端链表、哈希表之类的数据结构,它节省了大量的内存分配和管理开销。并且,在元素个数较少的情况下,它可以更快地处理命令请求,其中包括插入、删除和遍历操作。
classDiagram ZipList .. Entry class ZipList{ -[]byte data -int count -int tailIndex +Insert(entry) +Get(index) } class Entry { -int prevLen -[]byte data -Encoding encoding +Byte() }
特点
- Ziplist的内存分布连续,高效利用了cache line,可以减少内存碎片和操作次数。
- 可以通过偏移量快速计算每个节点的位置,并进行快速的定位和修改。这使得Ziplist的遍历与查找操作非常高效,时间复杂度为O(1)。
- Ziplist本身就具有压缩性,节点数量较少时,可以极大地节约内存空间。如果列表已经达到了一定大小或者需要频繁更新,则Redis会自动将其转换成基于双端链表或者散列表的数据结构。
实现
1 | package main |
- 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import (
"encoding/binary"
"github.com/stretchr/testify/assert"
"testing"
)
func TestZipList(t *testing.T) {
list := New()
list.Insert(NewStringEntry("foo"))
list.Insert(NewStringEntry("bar"))
list.Insert(NewIntEntry(10086))
assert.Equal(t, "foo", string(list.Get(0)))
assert.Equal(t, "bar", string(list.Get(1)))
assert.Equal(t, uint32(10086), binary.BigEndian.Uint32(list.Get(2)))
}
- 本文作者: Hongker
- 本文链接: https://hongker.github.io/2023/05/05/algorithm-ziplist/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!