重現Redis 資料結構與物件(三)

2021-08-11 10:40:49 字數 1343 閱讀 9699

整數集合(intset)是集合鍵的底層實現之一,當乙個集合只有整數值元素且元素不多時,redis使用整數集合作為集合鍵的底層實現。

定義和實現分別在intset.h和intset.c中。

typedef struct intset  intset;
redis可以儲存的整數值型別為int16_t, int32_t, int64_t 並且保證集合中不會出現重複的元素。

contents陣列是intset的底層實現,兩個特點:有序 無重複。

值得一說的是,contents使用的型別是int8_t,但是實際儲存的是16, 32或64位的數值,由encoding確定。

可以看見有下面一系列的巨集:

/* note that these encodings are ordered, so:

* intset_enc_int16 < intset_enc_int32 < intset_enc_int64. */

#define intset_enc_int16 (sizeof(int16_t))

#define intset_enc_int32 (sizeof(int32_t))

#define intset_enc_int64 (sizeof(int64_t))

在插入乙個新元素的時候,新元素型別比現有集合中所有的元素型別都要長的時候,整數集合需要先進行公升級操作,然後才可以將新元素新增到整數集合中。

1.根據新元素型別重新計算拓展空間,這裡涉及空間重分配

2.將底層陣列現有的元素轉換成新元素相同的型別,並根據有序性把原來的元素依次放到對應位置

3.將新元素新增進入集合中

4.最後,encoding屬性改變

另外一提的是:intset只支援公升級不支援降級,也就是說一旦公升級編碼就會一直保持公升級後的狀態。

值得吐槽的是:這個資料結構插入效率o(n)… 實在是很慢了也確實很遜色

關於api,介面都在標頭檔案給出了,實在比較普通。

關於int成員的set和get方法可以想象:其實也就是根據encoding的值,在陣列上進行了相關的操作,非常簡單~在封裝上,外層函式提供了乙個簡單的邊界判斷,防止定址的pos是錯誤的。

可以簡單看看公升級的**:

static intset *intsetresize(intset *is, uint32_t len) 

static intset *intsetupgradeandadd(intset *is, int64_t value)

is結構體萬一分配失敗,那麼zrealloc將會終止整個程式…

這裡沒有單獨去做過多的處理,而直接粗暴地解決了。。。可怕

redis 資料結構與物件

簡單說下redis的資料結構,這些在網上也都有很詳細的解釋,redis 設計與實現 這本書基於redis3.0的,但是現在已經5.0 了,所以有些資料結構發生了變化,其中我自己實現發現了一部分,可能還有沒發現的。慢慢實踐吧 簡單動態字串是在c語音傳統的字串基礎上構建的,其資料結構為 struct s...

Redis資料結構與物件

redis使用五種型別物件實現實現鍵值對資料庫 字串 列表 雜湊 集合 有序集合 列表編碼 ziplist或linkedlist 雜湊編碼 ziplist或hashtable 集合編碼 intset或hashtable 有序集合編碼 ziplist或skiplist struct sdshdr 二進...

Redis資料結構與物件(二)

1 物件共享 如果redis中已經set了乙個字串或數字,再set同樣值,這時會實現物件引用共享。值物件的refcount會出現變化,增加。redis set a 100 ok redis set b 100 redis object refcount a integer 2 object refc...