redis資料結構:整數集合
整數集合
整數集合是集合鍵的底層實現之一, 當一個集合只包含整數值元素, 並且這個集合的元素數量不多時, Redis 就會使用整數集合作為集合鍵的底層實現。
整數集合(intset)是 Redis 用於儲存整數值的集合抽象資料結構, 它可以儲存型別為 int16_t 、 int32_t 或者 int64_t 的整數值, 並且保證集合中不會出現重複元素而且集合是有序的。
typedef struct intset { // 編碼方式 uint32_t encoding; // 集合包含的元素數量 uint32_t length; // 儲存元素的陣列 int8_t contents[]; } intset;
encoding:控制陣列元素多少位
length:陣列有多少個元素
contents:陣列
整數集合的升級
每當我們要將一個新元素新增到整數集合裡面, 並且新元素的型別比整數集合現有所有元素的型別都要長時, 整數集合需要先進行升級(upgrade), 然後才能將新元素新增到整數集合裡面。
升級整數集合並新增新元素共分為三步進行:
- 根據新元素的型別, 擴充套件整數集合底層陣列的空間大小, 併為新元素分配空間。
- 將底層陣列現有的所有元素都轉換成與新元素相同的型別, 並將型別轉換後的元素放置到正確的位上, 而且在放置元素的過程中, 需要繼續維持底層陣列的有序性質不變。
- 將新元素新增到底層數組裡面。
升級之後新元素的擺放位置
因為引發升級的新元素的長度總是比整數集合現有所有元素的長度都大, 所以這個新元素的值要麼就大於所有現有元素, 要麼就小於所有現有元素:
- 在新元素小於所有現有元素的情況下, 新元素會被放置在底層陣列的最開頭(索引 0 );
- 在新元素大於所有現有元素的情況下, 新元素會被放置在底層陣列的最末尾(索引 length-1 )。
升級有什麼好處
整數集合不支援降級操作, 一旦對陣列進行了升級, 編碼就會一直保持升級後的狀態。
提升靈活性
因為 C 語言是靜態型別語言, 為了避免型別錯誤, 我們通常不會將兩種不同型別的值放在同一個資料結構裡面。
比如說, 我們一般只使用 int16_t 型別的陣列來儲存 int16_t 型別的值, 只使用 int32_t 型別的陣列來儲存 int32_t 型別的值, 諸如此類。
但是, 因為整數集合可以通過自動升級底層陣列來適應新元素, 所以我們可以隨意地將 int16_t 、 int32_t 或者 int64_t 型別的整數新增到集合中, 而不必擔心出現型別錯誤, 這種做法非常靈活。
節約記憶體
如果我們一直只向整數集合新增 int16_t 型別的值, 那麼整數集合的底層實現就會一直是 int16_t 型別的陣列, 只有在我們要將 int32_t 型別或者 int64_t 型別的值新增到集合時, 程式才會對陣列進行升級。