Redis 原理 - Sorted Set (ZSet)

来源:https://www.cnblogs.com/broadm/archive/2022/06/29/16424133.html
-Advertisement-
Play Games

Sorted Set (ZSet) 數據結構 Sorted Set (ZSet), 即有序集合, 底層使用 壓縮列表(ziplist) 或者 跳躍表(skiplist) 使用 壓縮列表(ziplist) 當同時滿足下麵兩個條件時,使用 ziplist 存儲數據 元素個數少於128個 (zset-ma ...


Sorted Set (ZSet) 數據結構

  • Sorted Set (ZSet), 即有序集合, 底層使用 壓縮列表(ziplist) 或者 跳躍表(skiplist)

    1. 使用 壓縮列表(ziplist)
      當同時滿足下麵兩個條件時,使用 ziplist 存儲數據
      • 元素個數少於128個 (zset-max-ziplist-entries: 128)
      • 每個元素長度小於64位元組 (zset-max-ziplist-value: 64)
    2. 不滿足上面的條件, 使用 跳躍表(skiplist)
      • zset 在轉為 skiplist 之後,即使元素被逐漸刪除,也不會重新轉為 ziplist
  • 有趣的命名: Sorted Set 為啥不縮寫為 SSet ? GitHub有人提問

    • Z代表XYZ中的Z, 所以有排序的意思(這個說法有點牽強吧)
    • Set命令已經使用S作為首碼了, 所以Sorted Set不再使用S (可信度較高)
    • SSet 很奇怪, 很難發音 (這個理由也可以接受)

使用 ziplist 圖解

zset_ziplist_數據結構.png

使用 skiplist 圖解

skiplist 定義

跳錶是一種數據結構。它使得包含n個元素的有序序列的查找和插入操作的平均時間複雜度都是 O(logn),優於數組的 O(n)複雜度。快速的查詢效果是通過維護一個多層次的鏈表實現的,且與下麵一層鏈表元素的數量相比,每一層鏈表中的元素的數量更少。

skiplist 數據結構

//跳躍表節點
typedef struct zskiplistNode {
    robj *obj; // 成員對象
    double score; // 分值
    struct zskiplistNode *backward; // 後退指針
    // 層
    struct zskiplistLevel {
        struct zskiplistNode *forward; // 前進指針
        unsigned int span; // 跨度
    } level[];
} zskiplistNode;

//跳躍表
typedef struct zskiplist {
    struct zskiplistNode *header, *tail; // 表頭節點和表尾節點
    unsigned long length; // 表中節點的數量
    int level; // 表中層數最大的節點的層數
} zskiplist;

//有序集合
typedef struct zset {
    dict *dict; // 字典,鍵為成員,值為分值, 用於支持 O(1) 複雜度的按成員取分值操作
    zskiplist *zsl; // 跳躍表,按分值排序成員, 用於支持平均複雜度為 O(log N) 的按分值定位成員操作, 以及範圍操作
} zset;

skiplist 圖解

skiplist.jpg

簡單說下skiplist的查找過程:

比如查詢 分數比 broadm 小的用戶名

  1. 使用zset中的字典dict快速獲取broadm節點對應的score=4
  2. 從header節點的最高層(第5層)出發,最高層(第5層)的前進節點是 obj:mike score:3,對比發現,此節點的score=3, 小於要查詢的節點的score=4 (說明目標節點在此節點的右邊), 應該繼續前進, 但是此節點沒有前進節點了, 那就降低一層,直到找到有前進節點的層為止(這裡是第2層)
  3. 第2層的前進節點就是 broadm 了,找到了
  4. 因為skiplist是有序的,並且每個節點都保存了 backward 指針, 所以直接遍歷鏈表就可以獲取分數比broadm小的節點了

這裡的數據量比較少,不容易看出來效果, 當數據量很大的時候,這種查詢是非常高效的,平均時間複雜度為 O(logn),基本和平衡二叉樹等效

Redis使用skiplist而不是紅黑樹的原因?

  • 紅黑樹實現細節過於複雜,比如為了保持平衡,需要做節點的旋轉操作, 而skiplist完全是靠隨機層數實現的自平衡,非常簡單
  • 在範圍查找時,跳躍表明顯優於紅黑樹, 跳躍表是有序的鏈表,直接遍歷後繼節點即可, 而紅黑樹需要中序遍歷,複雜度更高

Sorted Set (ZSet) 常用命令

  • ZADD key score member 添加一個或多個元素到集合中,如果已經存在,則更新其score
  • ZREM key member 刪除集合中的指定元素
  • ZSCORE key member 獲取集合中指定元素的score
  • ZRANK key member 獲取集合中指定元素的排名(從0開始)
  • ZCARD key 獲取集合中元素的個數
  • ZCOUNT key min max 統計score在閉區間[min,max]的元素的個數
  • ZRANGE key min max 獲取指定排名範圍內的元素
  • ZDIFF, ZINTER, ZUNION 求多個集合的 差集,交集,並集

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 來源:blog.csdn.net/qq_29879799/article/details/105146415 java的stream編程給調試帶來了極大的不便,idea 推出了streamtrace功能,可以詳細看到每一步操作的關係、結果,非常方便進行調試。 初遇StreamTrace 這裡簡單將字 ...
  • The DataStream API gets its name from the special DataStream class that is used to represent a collection of data in a Flink program. You can think of ...
  • 參考:(17條消息) 手把手搭建一個完整的javaweb項目(適合新手)_心歌技術的博客-CSDN博客_javaweb項目完整案例 補充項目結構的細節,進行了一點修改,修改為學生信息管理系統 以下是搭建過程: 1.項目結構 2.資料庫結構 3.代碼部分 com.dao.StuDao.java pac ...
  • 背景:[JAVA]前幾天面試超碧,聊到其接觸的項目,有抓取各類排行的實時數據,進行多國語言翻譯,抓取目前比較火的語言是php、go,由於目前工作使用JAVA,因此也模擬實現了一下抓取百度熱搜榜實時數據。 效果: 步驟: 1、定址【百度熱搜榜】https://top.baidu.com/board?t ...
  • java集合 學習資源:b站 人人都是程式員 《看動畫學java集合》 b站 韓順平 《java集合》 感謝二位的開源視頻,本博客為個人筆記,如有錯誤還請包涵 學習方法:推薦觀看視頻,自己用idea敲一遍然後debug一步步看,最後自己寫筆記和畫流程圖。 前 言 目的:為了方便和高效地存儲大批量的數 ...
  • Hi,大家好,我是Mic。 一個工作5年的粉絲,在簡歷上寫精通Kafka。 結果在面試的時候直接打臉。 面試官問他:“什麼是ISR,為什麼需要設計ISR” 然後他一臉懵逼的看著面試官. 下麵看看普通人和高手的回答。 普通人: ISR好像是Kafka裡面的一個機制吧。 為什麼要引入,應該是跟數據同步有 ...
  • runAsync 和 supplyAsync runAsync接受一個Runable的實現,無返回值 CompletableFuture.runAsync(()->System.out.println("無返回結果的運行")); supplyAsync接受一個Supplier的實現,有返回值 Com ...
  • 前言 🗯 嗨嘍,大家好呀~這裡是愛看美女的茜茜吶 水印這個詞相信大家已經不陌生了,畢竟現今天, 視頻有水印,圖片有水印,甚至一些電商平臺的展示圖也有水印 🍬 於是今天我就來分享一個python添加水印的方法~學會後你就不用自己去添加水印了, 只需要點一下運行~ python它自己自己給你弄好啦! ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...