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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...