intset
當一個集合中只包含整數,且這個集合中的元素數量不多時,redis就會使用整數集合intset作為集合的底層實現。 整數集合的實現
typedef struct intset { uint32_t encoding; uint32_t length; int8_t contents[];} intset; encoding:當前整數集合的編碼方式 length:集合中的元素個數 contents:集合中元素的具體儲存位置
redis整數集合有三種編碼方式:
1)INTSET_ENC_INT16,那麼contents數組就是一個int16_t類型的數組,數組中的每一項都是一個int16_t類型的整數,範圍為-32768~32767
2)INTSET_ENC_INT32,那麼contents是一個int32_t類型的數組
3)INTSET_ENC_INT64,那麼contents是一個int64_t類型的數組 示意圖
一個簡單的示意圖如下:
數組中的每個元素都是int16_t類型的,2個位元組,一個有5個元素,因此contents數組佔用的空間為 16*5/8=10位元組 升級
假設原有整數集合為:
此時contents數組佔用的空間為16*3=48位
對於int16_t類型的元素,其範圍為-32768~32767,當新加入一個值為65535的元素時,int16_t類型就不足以存放該元素,因此此時就要對整數集合進行升級。
該元素用int32_t足夠儲存,因此要將整數集合的編碼方式升級為INTSET_ENC_INT32。
這樣就需要 32*4=128位的空間,每個元素佔4個位元組。
因此升級的步驟為:
1)根據新元素的類型,擴充底層數組的空間大小,並分配空間
2)將底層所有元素都轉換成新元素相同的類型,並將轉換後的元素放到新分配的空間中。在放置元素的過程中,需要維持底層數組的有序性質不變
3)將新元素加入到底層數組中
由於新加入的元素導致升級,因此新元素的大小一定比之前所有的元素都大,因此將新元素存放在contents數組的最後一項即可
升級後的整數集合為:
contents數組中的元素存放順序為:
整數集合不支援降級操作
本文所引用的源碼全部來自Redis3.0.7版本
redis學習參考資料:
https://github.com/huangz1990/redis-3.0-annotated
Redis 設計與實現(第二版)