圖解Redis之數據結構篇——整數集合

文章導航-readme

前言

    整數集合(intset)並非一個基礎的數據結構,而是Redis本身設計的一種存儲結構,是集合鍵的底層實現之一,當一個集合只包含整數值元素,而且這個集合的元素數量很少時, Redis i就會使用整數集合做爲集合鍵的底層實現。html

1、整數集合實現

    整數集合(intset)是Redis用於保存整數值的集合抽象數據結構,它能夠保存類型爲int16_t、int32_t或者int64_t的整數值,而且保證集合中不會出現重複元素。數組

//每一個intset結構表示一個整數集合
typedef struct intset{
    //編碼方式
    uint32_t encoding;
    //集合中包含的元素數量
    uint32_t length;
    //保存元素的數組
    int8_t contents[];
} intset;
  • contents數組是整數集合的底層實現,整數集合的每一個元素都是 contents數組的個數組項(item),各個項在數組中按值的大小從小到大有序地排列,而且數組中不包含任何重複項。
  • length屬性記錄了數組的長度。
  • intset結構將contents屬性聲明爲int8_t類型的數組,但實際上 contents數組並不保存任何int8t類型的值, contents數組的真正類型取決於encoding屬性的值。encoding屬性的值爲INTSET_ENC_INT16則數組就是uint16_t類型,數組中的每個元素都是int16_t類型的整數值(-32768——32767),encoding屬性的值爲INTSET_ENC_INT32則數組就是uint32_t類型,數組中的每個元素都是int16_t類型的整數值(-2147483648——2147483647)。

int16_t

    如上圖,爲一int16_t類型的整數集合,咱們能夠看到數組中存儲了5個int16_t類型的整數,它們按照從小到大的順序依次排列。這個時候咱們思考一個問題。若是這個時候存入一個int32_t類型的整數會怎麼樣?內存溢出?這個時候就要提到整數集合的升級。數據結構

2、整數集合的升級

2.1 整數集合升級過程

    正如上面所提到的問題,每當咱們要將一個新元素添加到整數集合裏面,而且新元素的類型比整數集合現有全部元素的類型都要長時,整數集合須要先進行升級,而後才能將新元素添加到整數集合裏面。升級整數集合並添加新元素主要分三步來進行。運維

  1. 根據新元素的類型,擴展整數集合底層數組的空間大小,併爲新元素分配空間。
  2. 將底層數組現有的全部元素都轉換成與新元素相同的類型,並將類型轉換後的元素放置到正確的位上,並且在放置元素的過程當中,須要繼續維持底層數組的有序性質不變。
  3. 將新元素添加到底層數組裏面。

2.2 整數集合升級的優勢

  1. 提高靈活性

    由於C語言是靜態類型語言,爲了不類型錯誤,咱們一般不會將兩種不一樣類型的值放在同一個數據結構裏面。ui

    例如,咱們通常只使用int16_t類型的數組來保存int16_t類型的值,只使用int32_t類型的數組來保存int32_t類型的值,諸如此類。可是,由於整數集合能夠經過自動升級底層數組來適應新元素,因此咱們能夠隨意地將int16_t、int32_t或者int64_t類型的整數添加到集合中,而沒必要擔憂出現類型錯誤,這種作法很是靈活。編碼

  1. 節約內存

    要讓一個數組能夠同時保存int16_t、int32_t、int64_t三種類型的值,最簡單的作法就是直接使用int64t類型的數組做爲整數集合的底層實現。不過這樣一來,即便添加到整數集合裏面的都是int16_t類型或者int32_t類型的值,數組都須要使用int64_t類型的空間去保存它們,從而出現浪費內存的狀況。設計

而整數集合如今的作法既可讓集合能同時保存三種不一樣類型的值,又能夠確保升級操做只會在有須要的時候進行,這能夠儘可能節省內存。若是咱們一直只向整數集合添加int16_t類型的值,那麼整數集合的底層實現就會一直是int16_t類型的數組,只有在咱們要將int32_t類型或者int64_t類型的值添加到集合時,程序纔會對數組進行升級。code

2.3 降級

    整數集合不支持降級操做,一旦對數組進行了升級,編碼就會一直保持升級後的狀態。也就是說一旦咱們向一個int16_t的整數集合內添加了一個int32_t的元素後,整數集合將升級到int32_t類型。即便後續的操做中咱們刪除了這個元素,整數集合仍是會保持int32_t類型的狀態。htm

3、整數集合經常使用操做時間複雜度

操做 時間複雜度
建立一個新的整數集合 O(1)
添加指定元素到集合 O(N)
移除指定元素 O(N)
判斷指定元素是否在集合中 O(logN)
隨機返回一個元素 O(1)
取出在指定索引上的元素 O(1)
返回集合包含的元素個數 O(1)
返回集合佔用的內存字節數 O(1)

本文重點

  • 整數集合是Redis本身設計的一種存儲結構,集合鍵的底層實現之一。
  • 整數集合的底層實現爲數組,這個數組以有序、無重複的方式保存集合元素,在有須要時,程序會根據新添加元素的類型,改變這個數組的類型。
  • 升級操做爲整數集合帶來了操做上的靈活性,而且儘量地節約了內存。
  • 整數集合只支持升級操做,不支持降級操做。

參考

《Redis設計與實現》blog

《Redis開發與運維》

《Redis官方文檔》

-----END-----

相關文章
相關標籤/搜索