最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis數(shù)據(jù)結(jié)構(gòu)之Set結(jié)構(gòu)詳解

 更新時間:2026年05月09日 09:55:44   作者:難釋懷  
本文介紹了Redis中Set集合的數(shù)據(jù)結(jié)構(gòu),主要其Int種兩種編碼方式IntSet和Dict以及如何根據(jù)數(shù)據(jù)特征自動切換,IntSet通過緊湊的整數(shù)布局實現(xiàn)極致內(nèi)存節(jié)?。籇ict則提供高效的唯一性校驗,兩種編碼方式和閾值機制共同實現(xiàn)了了Set的內(nèi)存效率和操作性能的間的平衡

一、前言:無序、唯一、高效的集合

在 Redis 的五大數(shù)據(jù)類型中,Set(集合) 是一個非常獨特且強大的存在。它天生具備兩個核心特性:

  • 元素唯一性:自動去重,確保集合內(nèi)不存在重復(fù)元素。
  • 無序性:元素沒有固定的順序(盡管 SMEMBERS 返回的順序是穩(wěn)定的)。

基于這兩個特性,Set 被廣泛應(yīng)用于:

  • 標簽系統(tǒng)(用戶興趣標簽、文章分類)
  • 共同好友/關(guān)注SINTER 交集運算)
  • 抽獎池SRANDMEMBER 隨機抽?。?/li>
  • 全局去重(如爬蟲 URL 去重)

但你是否想過,Redis 是如何在底層高效地實現(xiàn)“唯一性”和“快速查找”的?答案就藏在它的兩種精巧數(shù)據(jù)結(jié)構(gòu)中。

核心價值

Redis Set 的底層會根據(jù)數(shù)據(jù)特征,在 IntSet(整數(shù)集合)和 Dict(字典)之間智能切換,以實現(xiàn)內(nèi)存效率與操作性能的最佳平衡!

本文將帶你:

  • 拆解 IntSet 的緊湊內(nèi)存布局
  • 揭秘 Dict 如何實現(xiàn) O(1) 的唯一性校驗
  • 理解編碼轉(zhuǎn)換背后的閾值邏輯

二、Set 的雙重身份:IntSet 與 Dict

Redis Set 并非只有一種底層實現(xiàn),而是擁有兩種編碼(encoding),由 redisObject 的 encoding 字段決定:

編碼 (encoding)底層數(shù)據(jù)結(jié)構(gòu)適用場景
OBJ_ENCODING_INTSETIntSet (整數(shù)集合)所有元素都是整數(shù),且數(shù)量較少
OBJ_ENCODING_HTDict (字典/哈希表)元素包含非整數(shù),或整數(shù)數(shù)量過多

這種設(shè)計體現(xiàn)了 Redis “因地制宜” 的優(yōu)化哲學:對簡單、規(guī)則的數(shù)據(jù)用最省空間的結(jié)構(gòu);對復(fù)雜、龐大的數(shù)據(jù)用最高效的結(jié)構(gòu)。

三、編碼一:IntSet - 整數(shù)的極致壓縮

3.1 誕生背景

當一個 Set 中的所有元素都是整數(shù)時,使用通用的哈希表(Dict)來存儲顯得有些“大材小用”。因為哈希表需要為每個元素存儲一個完整的 dictEntry 結(jié)構(gòu)(包含 key, value, next 指針等),內(nèi)存開銷較大。

為了極致節(jié)省內(nèi)存,Redis 引入了 IntSet

3.2 源碼結(jié)構(gòu)

typedef struct intset {
    uint32_t encoding; // 編碼方式:INTSET_ENC_INT16, INTSET_ENC_INT32, INTSET_ENC_INT64
    uint32_t length;   // 元素個數(shù)
    int8_t contents[]; // 柔性數(shù)組,存儲實際的整數(shù)數(shù)據(jù)
} intset;

關(guān)鍵特性

  • 內(nèi)存連續(xù):所有整數(shù)緊密排列在 contents 數(shù)組中,無任何指針開銷。
  • 有序存儲:內(nèi)部元素按從小到大排序,為二分查找提供可能。
  • 類型升級encoding 字段決定了每個整數(shù)占用的字節(jié)數(shù)(2/4/8字節(jié))。

3.3 類型升級機制(核心!)

IntSet 最精妙的設(shè)計在于其動態(tài)類型升級能力。

  • 初始狀態(tài):插入第一個整數(shù) 5encoding = INTSET_ENC_INT16,每個元素占 2 字節(jié)。
  • 插入更大整數(shù):當插入一個超出當前 encoding 范圍的整數(shù)(如 70000,超過了 int16 的最大值 32767)時,IntSet 會自動將整個集合升級到 INTSET_ENC_INT32。

過程

  • 申請一塊新的、更大的內(nèi)存空間。
  • 將原有所有元素按新類型(如 int32)重新寫入新空間。
  • 更新 encoding 和 length 字段。
  • 釋放舊內(nèi)存。

注意:這個過程需要 O(N) 的時間復(fù)雜度和額外的內(nèi)存,但只會在必要時發(fā)生一次,之后的插入操作又恢復(fù) O(log N)(二分查找+插入)。

3.4 內(nèi)存優(yōu)勢

假設(shè)一個 Set 包含 1000 個 int16 范圍內(nèi)的整數(shù):

  • IntSet8 (header) + 1000 * 2 = 2008 bytes
  • Dict:每個 dictEntry 至少需要 8(key)+8(value)+8(next) = 24字節(jié),加上哈希表本身的桶數(shù)組,總內(nèi)存輕松超過 24000+ bytes。

內(nèi)存節(jié)省高達 90% 以上!

四、編碼二:Dict - 通用的高性能解決方案

一旦 Set 不再滿足 IntSet 的苛刻條件(出現(xiàn)非整數(shù),或整數(shù)太多),Redis 會立即將其轉(zhuǎn)換為 Dict(字典)。

4.1 為什么是 Dict?

Dict 是 Redis 的基石數(shù)據(jù)結(jié)構(gòu)之一,它是一個哈希表,天然具備以下特性:

  • O(1) 平均時間復(fù)雜度:用于添加 (SADD)、刪除 (SREM)、查找 (SISMEMBER) 操作。
  • 天然去重:哈希表的 key 本身就是唯一的,完美契合 Set 的“元素唯一”要求。

4.2 Dict 在 Set 中的特殊用法

在 Set 的場景下,Dict 的使用非常巧妙:

  • Key:存儲 Set 的元素(字符串或序列化后的整數(shù))。
  • Value統(tǒng)一設(shè)置為 NULL 指針。
// 偽代碼示意
dict *d = dictCreate(&setDictType, NULL);
dictAdd(d, "element1", NULL);
dictAdd(d, "element2", NULL);

優(yōu)勢:這樣既利用了 Dict 的高效哈希和唯一性保證,又省去了 Value 的內(nèi)存開銷。

4.3 漸進式 Rehash

Dict 本身也有一套精妙的擴容/縮容機制(漸進式 rehash),確保在數(shù)據(jù)量巨大時,單次操作的延遲依然很低。這部分內(nèi)容在此不展開,但它保證了即使 Set 包含百萬級元素,性能依然穩(wěn)定。

五、編碼轉(zhuǎn)換:閾值與觸發(fā)條件

Redis 通過兩個配置項來控制 Set 何時從 intset 轉(zhuǎn)換為 hashtable

配置項默認值說明
set-max-intset-entries512當 Set 中的整數(shù)元素數(shù)量超過此值時,即使全是整數(shù),也會轉(zhuǎn)換為 Dict。
隱式條件-當嘗試向一個 intset 編碼的 Set 中插入一個非整數(shù)值(如字符串)時,會立即觸發(fā)轉(zhuǎn)換。

設(shè)計考量

  • 512 這個閾值:是內(nèi)存效率和操作性能的平衡點。超過 512 個元素后,IntSet 的 O(log N) 查找和 O(N) 的插入(因需移動內(nèi)存)開銷開始顯現(xiàn),而 Dict 的 O(1) 優(yōu)勢則愈發(fā)明顯。
  • 即時轉(zhuǎn)換:保證了數(shù)據(jù)模型的一致性。一旦數(shù)據(jù)不再是“純整數(shù)”,就必須切換到通用模型。

六、動手實驗:觀察 Set 的編碼變化

6.1 驗證 IntSet

# 添加純整數(shù)
> SADD myset 1 2 3 100 200
(integer) 5

# 查看編碼
> OBJECT ENCODING myset
"intset"

6.2 觸發(fā)轉(zhuǎn)換:插入非整數(shù)

# 插入一個字符串
> SADD myset "hello"
(integer) 1

# 編碼已變?yōu)?hashtable
> OBJECT ENCODING myset
"hashtable"

6.3 觸發(fā)轉(zhuǎn)換:超過閾值

# 創(chuàng)建一個腳本,添加513個整數(shù)
> for i in {1..513}; do redis-cli SADD big_intset $i; done

# 查看編碼(應(yīng)為 hashtable)
> OBJECT ENCODING big_intset
"hashtable"

七、總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Redis配置只讀賬號實現(xiàn)方式

    Redis配置只讀賬號實現(xiàn)方式

    本文介紹了Redis的ACL系統(tǒng),用于精細化管理不同用戶對Redis的訪問權(quán)限,從創(chuàng)建只讀賬戶、設(shè)置命令控制、鍵空間控制到權(quán)限類別等,詳細闡述了Redis6.0及以上版本的ACL配置方法,并提供了配置示例和管理命令,適用于提高數(shù)據(jù)安全性與管理效率
    2026-04-04
  • Redis慢日志的實現(xiàn)示例

    Redis慢日志的實現(xiàn)示例

    慢查詢?nèi)罩臼荝edis提供的一個用于觀察系統(tǒng)性能的功能,本文主要介紹了Redis慢日志的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-04-04
  • redis中的數(shù)據(jù)結(jié)構(gòu)和編碼詳解

    redis中的數(shù)據(jù)結(jié)構(gòu)和編碼詳解

    本文主要和大家分享幾種Redis數(shù)據(jù)結(jié)構(gòu)詳解,希望文中的案例和代碼,能幫助到大家。
    2020-03-03
  • Redis 過期鍵刪除策略的實現(xiàn)示例

    Redis 過期鍵刪除策略的實現(xiàn)示例

    Redis的過期數(shù)據(jù)刪除策略主要有三種,包括定時刪除、惰性刪除和定期刪除,本文主要介紹了Redis 過期鍵刪除策略的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • Redis實現(xiàn)商品秒殺的示例代碼

    Redis實現(xiàn)商品秒殺的示例代碼

    本文主要介紹了Redis實現(xiàn)商品秒殺的示例代碼,詳細介紹了Redis的List、Set和Hash類型,以及使用Redis事務(wù)保證原子性的方式,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • redisTemplate.opsForValue().get()獲取值失敗的解決方案

    redisTemplate.opsForValue().get()獲取值失敗的解決方案

    文章討論了在使用RedisTemplate時遇到get()方法返回null的問題,并分析了原因,作者建議使用@Autowired注解進行依賴注入,特別是推薦通過構(gòu)造函數(shù)注入,以避免類型無法分辨的問題,文章最后總結(jié)了這些經(jīng)驗,并鼓勵讀者參考和使用
    2026-03-03
  • Redis中Hash類型相關(guān)命令介紹

    Redis中Hash類型相關(guān)命令介紹

    Redis?hash是一個String類型的field和value的映射表,hash特別適合用于存儲對象,這篇文章主要介紹了Redis中Hash類型相關(guān)命令的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-12-12
  • Redis實現(xiàn)短信驗證碼登錄的示例代碼

    Redis實現(xiàn)短信驗證碼登錄的示例代碼

    本文主要介紹了基于Redis如何實現(xiàn)短信驗證碼登錄功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • Redis 常用命令之基礎(chǔ)、進階與場景化實戰(zhàn)案例

    Redis 常用命令之基礎(chǔ)、進階與場景化實戰(zhàn)案例

    Redis常用命令全解析,涵蓋基礎(chǔ)、進階和場景化實戰(zhàn),包括字符串、哈希、列表、集合、有序集合等數(shù)據(jù)類型,以及發(fā)布訂閱、分布式鎖、事務(wù)等高級功能,本文給大家介紹Redis常用命令之基礎(chǔ)、進階與場景化實戰(zhàn)案例,感興趣的朋友一起看看吧
    2026-01-01
  • redis stream 實現(xiàn)消息隊列的實踐

    redis stream 實現(xiàn)消息隊列的實踐

    本文主要介紹了redis stream 實現(xiàn)消息隊列的實踐,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08

最新評論

武宁县| 钟祥市| 甘谷县| 双流县| 百色市| 民县| 襄樊市| 宜春市| 达拉特旗| 玉山县| 阳原县| 姜堰市| 文安县| 临洮县| 绥滨县| 姚安县| 广东省| 印江| 扬州市| 荥经县| 武隆县| 嫩江县| 郸城县| 柳江县| 珠海市| 靖西县| 烟台市| 浦东新区| 平阴县| 菏泽市| 桃江县| 八宿县| 吴忠市| 屏山县| 邵东县| 东丰县| 文安县| 繁昌县| 霞浦县| 天台县| 蒙阴县|