Skip to content

Commit 461d487

Browse files
committed
[docs update] redis 有序集合底层实现完善
1 parent 510a823 commit 461d487

File tree

4 files changed

+2684
-3049
lines changed

4 files changed

+2684
-3049
lines changed

docs/about-the-author/readme.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
title: 个人介绍 Q&A
3+
category: 走近作者
4+
---
5+
6+
<!-- @include: @small-advertisement.snippet.md -->
7+
8+
这篇文章我会通过 Q&A 的形式简单介绍一下我自己。
9+
10+
## 我是什么时候毕业的?
11+
12+
很多老读者应该比较清楚,我是 19 年本科毕业的,刚毕业就去了某家外企“养老”。
13+
14+
我的学校背景是比较差的,高考失利,勉强过了一本线 20 来分,去了荆州的一所很普通的双非一本。不过,还好我没有因为学校而放弃自己,反倒是比身边的同学都要更努力,整个大学还算过的比较充实。
15+
16+
下面这张是当时拍的毕业照(后排最中间的就是我):
17+
18+
![](https://oss.javaguide.cn/javaguide/%E4%B8%AA%E4%BA%BA%E4%BB%8B%E7%BB%8D.png)
19+
20+
## 我坚持写了多久博客?
21+
22+
时间真快啊!我自己是从大二开始写博客的。那时候就是随意地在博客平台上发发自己的学习笔记和自己写的程序。就比如 [谢希仁老师的《计算机网络》内容总结](../cs-basics/network/computer-network-xiexiren-summary.md) 这篇文章就是我在大二学习计算机网络这门课的时候对照着教材总结的。
23+
24+
身边也有很多小伙伴经常问我:“我现在写博客还晚么?”
25+
26+
我觉得哈!如果你想做什么事情,尽量少问迟不迟,多问自己值不值得,只要你觉得有意义,就尽快开始做吧!人生很奇妙,我们每一步的重大决定,都会对自己未来的人生轨迹产生影响。是好还是坏,也只有我们自己知道了!
27+
28+
对我自己来说,坚持写博客这一项决定对我人生轨迹产生的影响是非常正面的!所以,我也推荐大家养成坚持写博客的习惯。
29+
30+
## 我在大学期间赚了多少钱?
31+
32+
在校期间,我还通过办培训班、接私活、技术培训、编程竞赛等方式变现 20w+,成功实现“经济独立”。我用自己赚的钱去了重庆、三亚、恩施、青岛等地旅游,还给家里补贴了很多,减轻了父母的负担。
33+
34+
下面这张是我大一下学期办补习班的时候拍的(离开前的最后一顿饭):
35+
36+
![补习班的最后一顿晚餐](https://oss.javaguide.cn/p3-juejin/f36bfd719b9b4463b2f1d3edc51faa97~tplv-k3u1fbpfcp-zoom-1.jpeg)
37+
38+
下面这张是我大三去三亚的时候拍的:
39+
40+
![](https://oss.javaguide.cn/javaguide/psc.jpeg)
41+
42+
其实,我在大学就这么努力地开始赚钱,也主要是因为家庭条件太一般,父母赚钱都太辛苦了!也正是因为我自己迫切地想要减轻父母的负担,所以才会去尝试这么多赚钱的方法。
43+
44+
我发现做咱们程序员这行的,很多人的家庭条件都挺一般的,选择这个行业的很大原因不是因为自己喜欢,而是为了多赚点钱。
45+
46+
如果你也想通过接私活变现的话,可以在我的公众号后台回复“**接私活**”来了解一些我的个人经验分享。
47+
48+
::: center
49+
50+
![](https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png)
51+
52+
:::
53+
54+
## 为什么自称 Guide?
55+
56+
可能是因为我的项目名字叫做 JavaGuide , 所以导致有很多人称呼我为 **Guide 哥**
57+
58+
后面,为了读者更方便称呼,我就将自己的笔名改成了 **Guide**
59+
60+
我早期写文章用的笔名是 SnailClimb 。很多人不知道这个名字是啥意思,给大家拆解一下就清楚了。SnailClimb=Snail(蜗牛)+Climb(攀登)。我从小就非常喜欢听周杰伦的歌曲,特别是他的《蜗牛》🐌 这首歌曲,另外,当年我高考发挥的算是比较失常,上了大学之后还算是比较“奋青”,所以,我就给自己起的笔名叫做 SnailClimb ,寓意自己要不断向上攀登,嘿嘿 😁
61+
62+
![](https://oss.javaguide.cn/p3-juejin/37599546f3b34b92a32db579a225aa45~tplv-k3u1fbpfcp-watermark.png)
63+
64+
## 后记
65+
66+
凡心所向,素履所往,生如逆旅,一苇以航。
67+
68+
生活本就是有苦有甜。共勉!
69+
70+
![JavaGuide 官方公众号](https://oss.javaguide.cn/github/javaguide/gongzhonghaoxuanchuan.png)

docs/database/redis/redis-skiplist.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ tag:
4040
6) "60"
4141
```
4242

43-
此时我们通过 `object` 指令查看 zset 的数据结构,可以看到当前有序集合存储的还是是**ziplist(压缩列表)**
43+
此时我们通过 `object` 指令查看 zset 的数据结构,可以看到当前有序集合存储的还是**ziplist(压缩列表)**
4444

4545
```bash
4646
127.0.0.1:6379> object encoding rankList
4747
"ziplist"
4848
```
4949

50-
因为设计者考虑到 Redis 数据存放于内存,为了节约宝贵的内存空间在有序集合在元素小于 64 字节且个数小于 128 的时候,会使用 ziplist,而这个阈值的默认值的设置就来自下面这两个配置项。
50+
因为设计者考虑到 Redis 数据存放于内存,为了节约宝贵的内存空间,在有序集合元素小于 64 字节且个数小于 128 的时候,会使用 ziplist,而这个阈值的默认值的设置就来自下面这两个配置项。
5151

5252
```bash
5353
zset-max-ziplist-value 64
@@ -78,7 +78,7 @@ zset-max-ziplist-entries 128
7878

7979
为了更好的回答上述问题以及更好的理解和掌握跳表,这里可以通过手写一个简单的跳表的形式来帮助读者理解跳表这个数据结构。
8080

81-
我们都知道有序链表在添加、查询、删除的平均时间复杂都都是**O(n)**即线性增长,所以一旦节点数量达到一定体量后其性能表现就会非常差劲。而跳表我们完全可以理解为在原始链表基础上,建立多级索引,通过多级索引检索定位将增删改查的时间复杂度变为**O(log n)**
81+
我们都知道有序链表在添加、查询、删除的平均时间复杂都都是 **O(n)** 即线性增长,所以一旦节点数量达到一定体量后其性能表现就会非常差劲。而跳表我们完全可以理解为在原始链表基础上,建立多级索引,通过多级索引检索定位将增删改查的时间复杂度变为 **O(log n)**
8282

8383
可能这里说的有些抽象,我们举个例子,以下图跳表为例,其原始链表存储按序存储 1-10,有 2 级索引,每级索引的索引个数都是基于下层元素个数的一半。
8484

@@ -145,8 +145,8 @@ r=n/2^k
145145
1. 跳表的高度计算从原始链表开始,即默认情况下插入的元素的高度为 1,代表没有索引,只有元素节点。
146146
2. 设计一个为插入元素生成节点索引高度 level 的方法。
147147
3. 进行一次随机运算,随机数值范围为 0-1 之间。
148-
4. 如果随机数大于 0.5 则为当前元素添加一级索引,自此我们保证生成一级索引的概率为**50%**,这也就保证了 1 级索引理想情况下只有一半的元素会生成索引。
149-
5. 同理后续每次随机算法得到的值大于 0.5 时,我们的索引高度就加 1,这样就可以保证节点生成的 2 级索引概率为**25%**,3 级索引为**12.5%**……
148+
4. 如果随机数大于 0.5 则为当前元素添加一级索引,自此我们保证生成一级索引的概率为 **50%** ,这也就保证了 1 级索引理想情况下只有一半的元素会生成索引。
149+
5. 同理后续每次随机算法得到的值大于 0.5 时,我们的索引高度就加 1,这样就可以保证节点生成的 2 级索引概率为 **25%** ,3 级索引为 **12.5%** ……
150150

151151
我们回过头,上述插入 7 之后,我们通过随机算法得到 2,即要为其建立 1 级索引:
152152

@@ -283,10 +283,10 @@ public void add(int value) {
283283

284284
查询逻辑比较简单,从跳表最高级的索引开始定位找到小于要查的 value 的最大值,以下图为例,我们希望查找到节点 8:
285285

286-
1. 跳表的 3 级索引首先找找到 5 的索引,5 的 3 级索引**forwards[3]**指向空,索引直接向下。
287-
2. 来到 5 的 2 级索引,其后继**forwards[2]**指向 8,继续向下。
288-
3. 5 的 1 级索引**forwards[1]**指向索引 6,继续向前。
289-
4. 索引 6 的**forwards[1]**指向索引 8,继续向下。
286+
1. 跳表的 3 级索引首先找找到 5 的索引,5 的 3 级索引 **forwards[3]** 指向空,索引直接向下。
287+
2. 来到 5 的 2 级索引,其后继 **forwards[2]** 指向 8,继续向下。
288+
3. 5 的 1 级索引 **forwards[1]** 指向索引 6,继续向前。
289+
4. 索引 6 的 **forwards[1]** 指向索引 8,继续向下。
290290
5. 我们在原始节点向前找到节点 7。
291291
6. 节点 7 后续就是节点 8,继续向前为节点 8,无法继续向下,结束搜寻。
292292
7. 判断 7 的前驱,等于 8,查找结束。
@@ -605,7 +605,7 @@ Node{data=23, maxLevel=1}
605605

606606
### 平衡树 vs 跳表
607607

608-
先来说说它和平衡树的比较,平衡树我们又会称之为 **AVL 树**,是一个严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过 1,即平衡因子为范围为 `[-1,1]`)。平衡树的插入、删除和查询的时间复杂度和跳表一样都是 **O(log n)**
608+
先来说说它和平衡树的比较,平衡树我们又会称之为 **AVL 树**,是一个严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过 1,即平衡因子为范围为 `[-1,1]`)。平衡树的插入、删除和查询的时间复杂度和跳表一样都是 **O(log n)**
609609

610610
对于范围查询来说,它也可以通过中序遍历的方式达到和跳表一样的效果。但是它的每一次插入或者删除操作都需要保证整颗树左右节点的绝对平衡,只要不平衡就要通过旋转操作来保持平衡,这个过程是比较耗时的。
611611

@@ -674,7 +674,7 @@ private Node add(Node node, K key, V value) {
674674

675675
### 红黑树 vs 跳表
676676

677-
红黑树(Red Black Tree)也是一种自平衡二叉查找树,它的查询性能略微逊色于 AVL 树,但插入和删除效率更高。红黑树的插入、删除和查询的时间复杂度和跳表一样都是 **O(log n)**
677+
红黑树(Red Black Tree)也是一种自平衡二叉查找树,它的查询性能略微逊色于 AVL 树,但插入和删除效率更高。红黑树的插入、删除和查询的时间复杂度和跳表一样都是 **O(log n)**
678678

679679
红黑树是一个**黑平衡树**,即从任意节点到另外一个叶子叶子节点,它所经过的黑节点是一样的。当对它进行插入操作时,需要通过旋转和染色(红黑变换)来保证黑平衡。不过,相较于 AVL 树为了维持平衡的开销要小一些。关于红黑树的详细介绍,可以查看这篇文章:[红黑树](https://javaguide.cn/cs-basics/data-structure/red-black-tree.html)
680680

@@ -726,7 +726,7 @@ private Node < K, V > add(Node < K, V > node, K key, V val) {
726726

727727
1. **多叉树结构**:它是一棵多叉树,每个节点可以包含多个子节点,减小了树的高度,查询效率高。
728728
2. **存储效率高**:其中非叶子节点存储多个 key,叶子节点存储 value,使得每个节点更够存储更多的键,根据索引进行范围查询时查询效率更高。-
729-
3. **平衡性**:它是绝对的平衡,即树的各个分支高度相差不大,确保查询和插入时间复杂度为**O(log n)**
729+
3. **平衡性**:它是绝对的平衡,即树的各个分支高度相差不大,确保查询和插入时间复杂度为 **O(log n)**
730730
4. **顺序访问**:叶子节点间通过链表指针相连,范围查询表现出色。
731731
5. **数据均匀分布**:B+树插入时可能会导致数据重新分布,使得数据在整棵树分布更加均匀,保证范围查询和删除效率。
732732

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"packageManager": "pnpm@9.11.0",
2323
"dependencies": {
2424
"@vuepress/bundler-vite": "2.0.0-rc.15",
25+
"@vuepress/plugin-feed": "2.0.0-rc.3",
2526
"@vuepress/plugin-search": "2.0.0-rc.47",
2627
"husky": "9.1.6",
2728
"markdownlint-cli2": "0.14.0",

0 commit comments

Comments
 (0)