Redis 的整數集合:像分類收納盒一樣的整數專屬存儲

目錄

一、先懂定位:為什么需要整數集合?(銜接哈希表)

二、整數集合的結構:像 “貼了規格標簽的收納盒”

1. encoding:收納盒的 “規格標簽”(核心:決定格子大小)

2. length:收納盒的 “物品數量”

3. contents:收納盒的 “有序格子”

三、核心操作:“升級”—— 從小盒子換大盒子(重點)

舉個具體例子:從 int16 升級到 int32

步驟 1:換大收納盒(擴展空間)

步驟 2:把小珠子換成大珠子(轉換元素類型)

步驟 3:放進新的大珠子(添加新元素)

3.1、為什么只能升級,不能降級?(Redis 的權衡)

四、適用場景:什么時候用整數集合?(對比哈希表)

五、總結:整數集合的設計邏輯(銜接 Redis 整體哲學)


如果說 SDS 是 “智能價簽”、壓縮列表是 “緊湊貨架”、字典是 “萬能儲物柜”,那整數集合(intset)?就是 Redis 為 “少量整數” 定制的分類收納盒—— 專門用來存純整數、數量不多的集合(比如SADD nums 10 20 30),核心優勢是 “省空間、保有序、無重復”。它和哈希表(hashtable)是集合鍵的兩種底層實現,就像收納時 “少量小物件用分類盒,大量 / 雜物件用儲物柜”。

一、先懂定位:為什么需要整數集合?(銜接哈希表)

之前學的哈希表(hashtable)?雖然能存集合(比如非整數元素SADD fruits "apple"),但有個 “內存浪費” 的問題:每個元素要存鍵(元素本身)和值(NULL,因為集合只需存存在性),還要處理哈希沖突。比如存 3 個小整數10、20、30,哈希表的指針、哈希槽等開銷,比整數本身的空間還大。

而整數集合的思路是:用 “統一規格的數組” 存整數,不存額外指針 / 哈希信息,還保持有序無重復—— 就像用 “帶格子的收納盒” 裝小珠子,每個格子只放一顆,按大小排好,沒有多余的包裝,省空間又好查找。

二、整數集合的結構:像 “貼了規格標簽的收納盒”

整數集合的底層是intset結構體,對應 “分類收納盒” 的三個核心部分:規格標簽、物品數量、收納格子。我們先看結構定義,再逐個類比拆解:

typedef struct intset {uint32_t encoding;   // 收納盒的“規格標簽”(存什么類型的整數)uint32_t length;     // 收納盒里的“物品數量”(元素個數)int8_t contents[];   // 收納盒的“格子數組”(實際存整數的地方)
} intset;

1. encoding:收納盒的 “規格標簽”(核心:決定格子大小)

encoding就像收納盒上貼的 “適用物品規格”,比如 “僅放直徑≤5mm 的小珠子”,它決定了contents數組實際能存什么類型的整數:

  • INTSET_ENC_INT16:“小格子規格”—— 每個格子存int16_t類型(范圍:-32768 ~ 32767),比如 10、20、32767。
  • INTSET_ENC_INT32:“中格子規格”—— 每個格子存int32_t類型(范圍:-2147483648 ~ 2147483647),比如 32768(超過 int16 最大值)、100000。
  • INTSET_ENC_INT64:“大格子規格”—— 每個格子存int64_t類型(范圍極大),比如 2147483648(超過 int32 最大值)。

關鍵注意:雖然contents聲明是int8_t(1 字節小格子),但實際格子大小由encoding決定!就像收納盒表面寫 “小格子”,但貼的規格標簽是 “中格子”,實際就能放大珠子 —— 這是 Redis 的 “靈活聲明”,為了兼容不同規格。

2. length:收納盒的 “物品數量”

length直接記錄收納盒里有多少個整數(無重復),比如存了 10、20、30,length=3。和壓縮列表的zllen類似,能快速獲取元素數量(O (1) 復雜度),不用數格子。

3. contents:收納盒的 “有序格子”

contents是實際存整數的數組,有兩個核心特性:

  • 有序:按從小到大排列,比如存 10、30、20,最終格子里是[10,20,30]—— 方便快速查找(用二分法,O (logN) 復雜度)。
  • 無重復:同一個整數不會出現兩次,比如再存 20,Redis 會檢查格子里已有,不重復添加 —— 就像收納盒里不會有兩顆一樣大的珠子。

三、核心操作:“升級”—— 從小盒子換大盒子(重點)

整數集合最特殊的邏輯是 “自動升級”:當要放的整數 “太大”(超過當前encoding的范圍),就必須把整個收納盒換成更大規格,再統一轉換原有元素的 “大小”,最后放進新元素。這就像 “小珠子收納盒里要放大珠子,必須先換大盒子,把原來的小珠子都換成大珠子,再放大珠子”。

舉個具體例子:從 int16 升級到 int32

假設現在有個 “小格子收納盒”(encoding=INTSET_ENC_INT16),已經放了兩個小整數:10、32767(int16 的最大值)。現在要放 32768(超過 int16 的最大值,必須用 int32),升級步驟對應生活場景:

步驟 1:換大收納盒(擴展空間)
  • 原來的小盒子:每個格子占 2 字節(int16),2 個元素共 4 字節。
  • 新的大盒子:每個格子占 4 字節(int32),需要存 3 個元素(原有 2 個 + 新 1 個),總空間 = 3×4=12 字節。
  • Redis 會申請 12 字節的新空間,代替原來的 4 字節 —— 就像把 2 格的小盒子,換成 3 格的大盒子。
步驟 2:把小珠子換成大珠子(轉換元素類型)
  • 不能直接把小珠子(int16 的 10、32767)放進大格子,必須先 “放大” 成大珠子(int32 的 10、32767)。
  • 轉換時要保持順序:原來小盒子里是[10,32767],轉換后大盒子的前兩格還是[10,32767](只是每個占 4 字節)—— 就像把小珠子裝進大托里,位置不變。
步驟 3:放進新的大珠子(添加新元素)
  • 把 32768(int32 類型)放進大盒子的最后一格,最終格子里是[10,32767,32768],保持有序。
  • 最后更新encoding為 INTSET_ENC_INT32,length為 3—— 收納盒的規格標簽和數量標簽同步更新。

3.1、為什么只能升級,不能降級?(Redis 的權衡)

升級后就算刪了 “大珠子”(比如把 32768 刪掉,只剩 10、32767),Redis 也不會把大盒子換回小盒子 —— 這就是 “無降級” 規則,原因很簡單:

  1. 麻煩且沒必要:降級需要先檢查所有元素是否都符合小規格,再轉換類型、縮小空間 —— 就像把大珠子換回小珠子,再換小盒子,步驟多,浪費時間。
  2. 效率優先:Redis 認為 “少量內存浪費” 比 “頻繁降級的性能損耗” 更劃算。比如大盒子里放小珠子,多占的內存不多(每個元素多 2 字節),但省去了降級的麻煩。
  3. 避免風險:如果降級后又要放大珠子,得再次升級,反復操作反而更慢 —— 就像換了小盒子又要換大的,不如一直用大的。

四、適用場景:什么時候用整數集合?(對比哈希表)

Redis 選擇整數集合還是哈希表,遵循 “整數優先、少量優先” 的原則,和壓縮列表的 “小數據優先” 思路一致:

集合類型底層實現原因(生活類比)
純整數元素 + 元素少(默認<512 個)整數集合分類收納盒存少量小珠子,省空間、好排序
非整數元素(如字符串)哈希表萬能儲物柜存雜物件,不管類型,查找快
純整數元素 + 元素多哈希表收納盒格子太多不好翻,儲物柜(哈希表)更快

舉例:

SADD nums 1 2 3(純整數、少元素)→ 整數集合;

SADD fruits "apple" "banana"(非整數)→ 哈希表;

SADD big_nums 1 2 ... 1000(多元素)→ 哈希表。

五、總結:整數集合的設計邏輯(銜接 Redis 整體哲學)

整數集合的所有設計,都和之前學的 SDS、壓縮列表、跳躍表一脈相承,體現 Redis“因地制宜、權衡取舍” 的核心思路:

  • SDS:用 “len+free” 平衡 “字符串擴展” 和 “內存浪費”—— 取舍:預分配少量空間換擴展效率;
  • 壓縮列表:用 “連續內存 + 可變標簽” 平衡 “內存節省” 和 “連鎖更新風險”—— 取舍:接受罕見更新換極致省內存;
  • 整數集合:用 “統一規格數組 + 自動升級” 平衡 “內存節省” 和 “類型兼容”—— 取舍:不支持降級換操作簡單、效率高。

簡單說,整數集合就是 Redis 為 “少量整數集合” 量身定制的 “高效收納盒”:它沒有哈希表的靈活,但勝在省空間、有序;沒有壓縮列表的復雜,勝在操作簡單、只存整數。這種 “專物專用” 的設計,正是 Redis 能兼顧性能和內存的關鍵。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97735.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97735.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97735.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux 進程狀態 — 僵尸進程

🎁個人主頁:工藤新一 🔍系列專欄:C面向對象(類和對象篇) 🌟心中的天空之城,終會照亮我前方的路 🎉歡迎大家點贊👍評論📝收藏?文章 文章目錄進…

React 中 key 的作用

React 中 key 的作用是什么? Date: August 31, 2025 Area: 原理key 概念 在 React 中,key 用于識別哪些元素是變化、添加或刪除的。 在列表渲染中,key 尤其重要,因為它能提高渲染性能和確保組件狀態的一致性。key 的作用 1&#x…

wpf之附加屬性

前言 附加屬性是 WPF 中一個非常強大和獨特的概念。簡單來說,它允許一個對象為另一個在其本身類定義中未定義的屬性賦值。 1、定義附加屬性 定義一個Watermark的附加屬性,該屬性的作用是將TextBox的附加屬性改變時,TextBox的字體顏色改成灰…

深入淺出 RabbitMQ-消息可靠性投遞

大家好,我是工藤學編程 🦉一個正在努力學習的小博主,期待你的關注實戰代碼系列最新文章😉C實現圖書管理系統(Qt C GUI界面版)SpringBoot實戰系列🐷【SpringBoot實戰系列】SpringBoot3.X 整合 Mi…

數字化時代,中小企業如何落地數字化轉型

大數據時代,各行各業的行業龍頭和大型集團都已經開始了數據管理,讓數據成為數據資產。但是在我國,中小企業的數量巨大,很多管理者忽視了這一點,今天我們就來聊一聊中小企業的數字化轉型。中小企業需要數字化轉型首先要…

Unity筆記(九)——畫線功能Linerenderer、范圍檢測、射線檢測

寫在前面:寫本系列(自用)的目的是回顧已經學過的知識、記錄新學習的知識或是記錄心得理解,方便自己以后快速復習,減少遺忘。這里只記錄代碼知識。十一、畫線功能Linerenderer畫線功能Linerenderer是Unity提供的畫線腳本,創建一個空…

刷題記錄(8)string類操作使用

一、僅反轉字母 917. 僅僅反轉字母 - 力扣(LeetCode) 簡單來說輸入字符串,要求你返回所有僅字母位置反轉后的字符串。 簡單看一個樣例加深理解: 前后互換,我想思路基本很明顯了,雙指針,或者說…

用好AI,從提示詞工程到上下文工程

前言 隨著 AI 大模型的爆發,提示詞工程(prompt engineering ) 一度是用戶應用 AI ,發揮 AI 能力最重要、也最應該掌握的技術。 但現在,在 “提示詞工程”的基礎上,一個更寬泛也更強力的演化概念被提出,也就是本文我們要介紹的 “上下文工程(Context Engineering)” …

計算機Python畢業設計推薦:基于Django+Vue用戶評論挖掘旅游系統

精彩專欄推薦訂閱:在下方主頁👇🏻👇🏻👇🏻👇🏻 💖🔥作者主頁:計算機畢設木哥🔥 💖 文章目錄 一、項目介紹二、…

? 肆 ? ? 默認安全:安全建設方案 ? a.信息安全基線

👍點「贊」📌收「藏」👀關「注」💬評「論」 在金融科技深度融合的背景下,信息安全已從單純的技術攻防擴展至架構、合規、流程與創新的系統工程。作為一名從業十多年的老兵,將系統闡述數字銀行安全體系的建設…

如何用AI視頻增強清晰度軟件解決畫質模糊問題

在視頻制作和分享過程中,畫質模糊、細節丟失等問題常常影響觀看體驗。無論是老舊視頻的修復還是低分辨率素材的優化,清晰度提升都成為用戶關注的重點。借助專業的AI技術,這些問題可以得到有效解決。目前市面上存在多種解決方案,能…

Linux92 shell:倒計時,用戶分類

問題 while IFS read -r line;doootweb kk]# tail -6 /etc/passwd user1r4:x:1040:1040::/home/user1r4:/bin/bash useros20:x:1041:1041::/home/useros20:/bin/bash useros21:x:1042:1042::/home/useros21:/bin/bash useros22:x:1043:1043::/home/useros22:/bin/bash useros23…

LinkedList源碼解析

1. 數據結構設計 (1) 節點結構 LinkedList 的核心是雙向鏈表節點 Node&#xff1a; private static class Node<E> {E item; // 存儲的元素Node<E> next; // 后繼節點Node<E> prev; // 前驅節點Node(Node<E> prev, E element, Node<E&g…

語雀批量導出知識庫

使用工具&#xff1a;yuque-dl 參考文檔&#xff1a; GitHub - gxr404/yuque-dl: yuque 語雀知識庫下載 Yuque-DL&#xff1a;一款強大的語雀資源下載工具_語雀文檔怎么下載-CSDN博客

電子電氣架構 --- 當前企業EEA現狀(下)

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

flink中的窗口的介紹

本文重點 無界流會源源不斷的產生數據,有的時候我們需要把無界流進行切分成一段一段的有界數據,把一段內的所有數據看成一個整體進行聚合計算,這是實現無界流轉成有界流的方式之一。 為什么需要窗口 數據是源源不斷產生的,我們可能只關心某個周期內的統計結果。比如電費…

自建es 通過Flink同步mysql數據 Docker Compose

資源es:7.18 kibana:7.18 flink:1.17.2目錄mkdir -p /usr/project/flink/{conf,job,logs} chmod -R 777 /usr/project/flink #資源情況 mysql8.0 Elasticsearch7.18 自建# 目錄結構 /usr/project/flink/ /usr/project/flink/ ├── conf/ │ ├── flink-conf.yaml │ └…

AI瀏覽器和釘釘ONE是不是偽需求?

最近兩則新聞格外引起了我的注意&#xff1a;一是Claude推出了官方瀏覽器插件&#xff0c;二是釘釘發布了釘釘ONE。前者說明AI瀏覽器未必有必要&#xff0c;后者則描繪了一幅“刷刷手機就能完成工作”的未來辦公圖景。這幾天我經常在思考&#xff0c;AI瀏覽器是不是沒有必要&am…

從結構化到多模態:RAG文檔解析工具選型全指南

在RAG系統建設中&#xff0c;文檔解析質量直接決定最終效果上限&#xff0c;選擇合適的解析工具已成為避免"垃圾進&#xff0c;垃圾出"&#xff08;GIGO&#xff09;困境的關鍵決策。一、文檔解析&#xff1a;RAG系統的基石與瓶頸 當前企業知識庫中超過80%的信息存儲…

設計模式:享元模式(Flyweight Pattern)

文章目錄一、享元模式的介紹二、實例分析三、示例代碼一、享元模式的介紹 享元模式&#xff08;Flyweight Pattern&#xff09; 是一種結構型設計模式。通過共享相同對象&#xff0c;減少內存消耗&#xff0c;提高性能。 它摒棄了在每個對象中保存所有數據的方式&#xff0c; 通…