整數集合(intset)是 Redis 用于保存整數值的集合抽象數據結構, 它可以保存類型為?`int16_t`?、?`int32_t`?或者?`int64_t`?的整數值, 并且保證集合中不會出現重復元素。
每個?`intset.h/intset`?結構表示一個整數集合:
~~~
typedef struct intset {
// 編碼方式
uint32_t encoding;
// 集合包含的元素數量
uint32_t length;
// 保存元素的數組
int8_t contents[];
} intset;
~~~
`contents`?數組是整數集合的底層實現: 整數集合的每個元素都是?`contents`?數組的一個數組項(item), 各個項在數組中按值的大小從小到大有序地排列, 并且數組中不包含任何重復項。
`length`?屬性記錄了整數集合包含的元素數量, 也即是?`contents`?數組的長度。
雖然?`intset`?結構將?`contents`?屬性聲明為?`int8_t`?類型的數組, 但實際上?`contents`?數組并不保存任何?`int8_t`?類型的值 ——?`contents`?數組的真正類型取決于?`encoding`?屬性的值:
* 如果?`encoding`?屬性的值為?`INTSET_ENC_INT16`?, 那么?`contents`?就是一個?`int16_t`?類型的數組, 數組里的每個項都是一個?`int16_t`?類型的整數值 (最小值為?`-32,768`?,最大值為?`32,767`?)。
* 如果?`encoding`?屬性的值為?`INTSET_ENC_INT32`?, 那么?`contents`?就是一個?`int32_t`?類型的數組, 數組里的每個項都是一個?`int32_t`?類型的整數值 (最小值為?`-2,147,483,648`?,最大值為?`2,147,483,647`?)。
* 如果?`encoding`?屬性的值為?`INTSET_ENC_INT64`?, 那么?`contents`?就是一個?`int64_t`?類型的數組, 數組里的每個項都是一個?`int64_t`?類型的整數值 (最小值為?`-9,223,372,036,854,775,808`?,最大值為?`9,223,372,036,854,775,807`?)。
圖 6-1 展示了一個整數集合示例:
* `encoding`?屬性的值為?`INTSET_ENC_INT16`?, 表示整數集合的底層實現為?`int16_t`?類型的數組, 而集合保存的都是?`int16_t`?類型的整數值。
* `length`?屬性的值為?`5`?, 表示整數集合包含五個元素。
* `contents`?數組按從小到大的順序保存著集合中的五個元素。
* 因為每個集合元素都是?`int16_t`?類型的整數值, 所以?`contents`?數組的大小等于?`sizeof(int16_t)?*?5?=?16?*?5?=?80`?位。

圖 6-2 展示了另一個整數集合示例:
* `encoding`?屬性的值為?`INTSET_ENC_INT64`?, 表示整數集合的底層實現為?`int64_t`?類型的數組, 而數組中保存的都是?`int64_t`?類型的整數值。
* `length`?屬性的值為?`4`?, 表示整數集合包含四個元素。
* `contents`?數組按從小到大的順序保存著集合中的四個元素。
* 因為每個集合元素都是?`int64_t`?類型的整數值, 所以?`contents`?數組的大小為?`sizeof(int64_t)?*?4?=?64?*?4?=?256`?位。

雖然?`contents`?數組保存的四個整數值中, 只有?`-2675256175807981027`?是真正需要用?`int64_t`?類型來保存的, 而其他的?`1`?、?`3`?、?`5`?三個值都可以用?`int16_t`?類型來保存, 不過根據整數集合的升級規則, 當向一個底層為?`int16_t`?數組的整數集合添加一個?`int64_t`?類型的整數值時, 整數集合已有的所有元素都會被轉換成?`int64_t`?類型, 所以?`contents`?數組保存的四個整數值都是?`int64_t`?類型的, 不僅僅是`-2675256175807981027`?。
接下來的一節將對整數集合的升級操作進行詳細的介紹。
- 介紹
- 前言
- 致謝
- 簡介
- 第一部分:數據結構與對象
- 簡單動態字符串
- SDS 的定義
- SDS 與 C 字符串的區別
- SDS API
- 重點回顧
- 參考資料
- 鏈表
- 鏈表和鏈表節點的實現
- 鏈表和鏈表節點的 API
- 重點回顧
- 字典
- 字典的實現
- 哈希算法
- 解決鍵沖突
- rehash
- 漸進式 rehash
- 字典 API
- 重點回顧
- 跳躍表
- 跳躍表的實現
- 跳躍表 API
- 重點回顧
- 整數集合
- 整數集合的實現
- 升級
- 升級的好處
- 降級
- 整數集合 API
- 重點回顧
- 壓縮列表
- 壓縮列表的構成
- 壓縮列表節點的構成
- 連鎖更新
- 壓縮列表 API
- 重點回顧
- 對象
- 對象的類型與編碼
- 字符串對象
- 列表對象
- 哈希對象
- 集合對象
- 有序集合對象
- 類型檢查與命令多態
- 內存回收
- 對象共享
- 對象的空轉時長
- 重點回顧
- 第二部分:單機數據庫的實現
- 數據庫
- 數據庫鍵空間
- 重點回顧
- RDB 持久化
- RDB 文件結構
- 重點回顧
- AOF 持久化
- AOF 持久化的實現
- 重點回顧
- 事件
- 文件事件
- 重點回顧
- 參考資料
- 客戶端
- 客戶端屬性
- 重點回顧
- 服務器
- 命令請求的執行過程
- 重點回顧
- 第三部分:多機數據庫的實現
- 復制
- 舊版復制功能的實現
- 重點回顧
- Sentinel
- 啟動并初始化 Sentinel
- 重點回顧
- 參考資料
- 集群
- 節點
- 重點回顧
- 第四部分:獨立功能的實現
- 發布與訂閱
- 頻道的訂閱與退訂
- 重點回顧
- 參考資料
- 事務
- 事務的實現
- 重點回顧
- Lua 腳本
- 創建并修改 Lua 環境
- 重點回顧
- 排序
- SORT <key> 命令的實現
- 重點回顧
- 二進制位數組
- GETBIT 命令的實現
- 重點回顧
- 慢查詢日志
- 慢查詢記錄的保存
- 慢查詢日志的閱覽和刪除
- 添加新日志
- 重點回顧
- 監視器
- 成為監視器
- 向監視器發送命令信息
- 重點回顧
- 源碼、相關資源和勘誤