徹底弄懂Redis set篇

2021-09-13 17:25:49 字數 2445 閱讀 6690

redis中有兩種集合,一種是無序集合,一種是有序集合,他們之間的相同點就是不重複,不同點就是是否有序,我們分別介紹一下。

因為set只要保證加入的元素不重複就好,所以他的底層實現也比較簡單,就是乙個value為空的雜湊表,key就是用來儲存加入的元素值的,我們今天重點介紹的就是sort set(有序集合)

有序集合是set的公升級版,在set的基礎上進行了排序,所以他必定要引入一種結構來完成排序的功能,也是我們介紹的重點,跳躍表。sort set的底層實現就是字典+跳躍表

跳躍表是由redis.h/zskiplistnode 和 redis.h/zskiplist 兩個結構定義, 其中 zskiplistnode 結構用於表示跳躍表節點, 而 zskiplist結構則用於儲存跳躍表節點的相關資訊。

我們分別看一下它們的結構:

redis.h/zskiplist

typedef struct zskiplist  zskiplist;
redis.h/zskiplistnode
typedef struct zskiplistnode  level;

} zskiplistnode;

在跳躍表中,儲存兩個節點,head,tail節點,節點的數量,以及層數。節點中有乙個後退指標,分值(依靠他的值進行排序),成員物件,他儲存的是乙個指標指向的是雜湊表中的插入的具體的值,乙個leve陣列,你可以把他理解成乙個鍊錶,每個成員都有乙個前進指標,和乙個跨度。

結構介紹的差不多了,再看一下結構圖:

這就是redis中乙個跳躍表的結構,可以根據他的原始碼結合理解一下,頭節點是不儲存值的,但是他保留著全部的層(l1-l32),這個是可以表示的最大層,並不是都會用到,然後我們向後看bw就是後退指標,1.0就是分值,o1就是儲存的物件(指標);

reids跳躍表在普通的跳躍表中做了一些改變,但是大致是相同的,如果你上面看懂了,下面一部分可以忽略,如果沒看懂你可以再根據這個理解一下

這就是乙個普通的跳躍表結構,其實大體上沒有什麼不同,一開始沒有值,後來一行就是一層,指向這一層的下乙個節點,再看每一列,他保留這這個物件參與的多層,他們的值都是一樣的,有兩個指標,乙個是前進指標,還有後退指標。大家試著理解一下

如果你能夠理解這種結構了,我們就看一下他的一些實現細節

有上面的圖可知,前進指標指向的就是某一層中後面的(比他分值大的)節點,所以也就是說我們可以通過前進指標找到最後乙個節點(也就是最大的),也就是前進指標為空時,

下面是乙個通過前進指標遍歷所有值的乙個過程圖:

有同學可以會疑惑箭頭上的數值是什麼,我們這就說了

層的跨度(level[i].span 屬性)用於記錄兩個節點之間的距離:

沒錯就是跨度,如果兩個數之間沒有跨過的數值,就是1,所以如果前進指標加上跨度就能遍歷表中所有的數值,如果不用跨度也能找到最大的數值

我們看虛線的內容,很明顯中間跨過了兩個數,但是其實是走了3步到最後的,所以跨度是3,其實我們還能觀察到,每一層的跨度,相加都是一樣的,這是必然的,因為目標都是一樣的,所以跨度也可以通過上一層的跨度相加獲得。

節點的後退指標(backward 屬性)用於從表尾向表頭方向訪問節點: 跟可以一次跳過多個節點的前進指標不同, 因為每個節點只有乙個後退指標, 所以每次只能後退至前乙個節點。

圖 5-6 用虛線展示了如果從表尾向表頭遍歷跳躍表中的所有節點: 程式首先通過跳躍表的 tail 指標訪問表尾節點, 然後通過後退指標訪問倒數第二個節點, 之後再沿著後退指標訪問倒數第三個節點, 再之後遇到指向 null 的後退指標, 於是訪問結束。

節點的分值(score 屬性)是乙個 double 型別的浮點數, 跳躍表中的所有節點都按分值從小到大來排序。

節點的成員物件(obj 屬性)是乙個指標, 它指向乙個字串物件, 而字串物件則儲存著乙個 sds 值。

注意節點的分值可以重複,但是物件的值是絕對不但能重複的,相同的分值會按照插入的順序排序。

我們按照o1,o2,o3的順序插入三個分值相同的節點

我介紹的就這麼多了,我是看《redis的設計與實現》學習的,有興趣的可以看一看,寫的還不錯

徹底弄懂session,cookie,token

我在寫之前看了很多篇session,cookie的文章,有的人說先有了cookie,後有了session。也有人說先有session,後有cookie。感覺都沒有講的很清楚,泛泛而談。希望本篇文章對大家有所幫助 注 本文需要讀者有cookie,session,token的相關基礎知識。什麼是無狀態呢...

徹底弄懂 Unicode 編碼

原文 今天,在學習 node.js 中的 buffer 物件時,注意到它的 alloc 和 from 方法會預設用utf 8編碼,在陣列中每位對應 1 位元組的十六進製制數。想到了之間學習 es6 時關於字串的 unicode 表示法,突然就很想知道 utf 16 是如何進行編碼的,我嘗試將一些漢字...

徹底弄懂React Redux元件通訊

為了方便使用,redux的作者封裝了乙個react專用的庫react redux,講解之前,先來了解一下什麼是容器元件和傻瓜元件?react redux把元件分為容器元件和傻瓜元件 ui元件 容器元件,負責和redux store打交道的元件,處於外層。功能 和redux store打交道,讀取st...