### 2.7.7 有序集合對象(zset)
有序集合對象的編碼(encoding)可以是`ziplist`、 `skipist`
當有序集合對象同時滿足以下兩個條件時,使用ziplist編碼,否則使用skiplist編碼:
- 所有元素長度小于64字節(可以通過`zset-max-ziplist-value`設置)
- 元素數量小于128個(可以通過`zset-max-ziplist-entries`設置)
----
skiplist編碼的對象使用zset作為底層數據結構:
```c
typedef struct zset {
zskiplist *zsl;
dict *dict;
};
```
- zsl中按分值c從小到大排列了所有元素,可以對集合進行范圍操作:ZRANK、ZRANGE等
- dict為所有元素創建了一個從成員到分值的映射,程序可以用O(1)的復雜度根據成員查找分值等,如ZSCORE
- 通過指針共享相同元素
----
```c
redis> ZADD price 8.5 apple 5.0 banana 6.0 cherry
(integer) 3
```
如果price鍵使用ziplist編碼,則其值對象如下所示:
```
redisObject
type: REDIS_ZSET
encoding: REDIS_ENCODING_ZIPLIST
ptr -> ziplist: {
zlbytes, zltail, zllen,"banana", 5.0, "cherry", 6.0, "apple", 8.5, zlend
}
...
```
如果price鍵使用skiplist編碼,則其值對象如下所示:
```
redisObject
type: REDIS_ZSET
encoding: REDIS_ENCODING_SKIPLIST
ptr -> zset: {
dict: {
dict, ..., h[0]: {
dictht, ..., table: {
(stringObject:"banana") -> 5.0
(stringObject:"apple") -> 8.5
(stringObject:"cherry") -> 6.0
}, ...
},...
},
zsl: {
(header: ...), (tail: ...), (level: 5), (length: 3)
}
}
...
```
----
有序集合命令的實現:
命令 | ziplist的實現 | skiplist的實現
---- | ---- | ----
ZAdd | 調用ziplistInsert函數,將成員和分值作為兩個結點分別插入到壓縮列表 | 先調用zslInsert函數插入跳躍表,再調用dictAdd函數插入到字典
ZCard | 調用ziplistLeng函數,將結果除以2后返回 | 返回跳躍表的length屬性
ZCount | 遍歷壓縮列表,統計分值在給定范圍內的結點數量 | 遍歷跳躍表,統計分值在給定范圍內的結點數量
ZRange | 從表頭到表尾遍歷壓縮列表,返回給定索引范圍內的所有元素 | 從表頭到表尾遍歷跳躍表,返回給定索引范圍內的所有元素
ZRevRange | 從表尾到表頭遍歷壓縮列表,返回給定索引范圍內的所有元素 | 從表尾到表頭遍歷跳躍表,返回給定索引范圍內的所有元素
ZRank | 從表頭到表尾遍歷壓縮列表,查找指定元素,返回途徑結點數,即排位 | 從表頭到表尾遍歷跳躍表,查找指定元素,返回途徑結點數,即排位
ZRevRank | 從表尾到表頭遍歷壓縮列表,查找指定元素,返回途徑結點數,即排位 | 從表尾到表頭遍歷跳躍表,查找指定元素,返回途徑結點數,即排位
ZRem | 遍歷壓縮列表,刪除所有包含給定成員的結點,及其下一個值結點 | 遍歷跳躍表,刪除所有包含了給定成員的跳躍表結點,并在字典中解除被刪除元素的成員和值的關聯
ZScore | 遍歷壓縮列表,查找指定成員結點,取出其下一個結點即值結點 | 直接在字典中取出給定成員所對應的值
- 空白目錄
- 精簡版Spring的實現
- 0 前言
- 1 注冊和獲取bean
- 2 抽象工廠實例化bean
- 3 注入bean屬性
- 4 通過XML配置beanFactory
- 5 將bean注入到bean
- 6 加入應用程序上下文
- 7 JDK動態代理實現的方法攔截器
- 8 加入切入點和aspectj
- 9 自動創建AOP代理
- Redis原理
- 1 Redis簡介與構建
- 1.1 什么是Redis
- 1.2 構建Redis
- 1.3 源碼結構
- 2 Redis數據結構與對象
- 2.1 簡單動態字符串
- 2.1.1 sds的結構
- 2.1.2 sds與C字符串的區別
- 2.1.3 sds主要操作的API
- 2.2 雙向鏈表
- 2.2.1 adlist的結構
- 2.2.2 adlist和listNode的API
- 2.3 字典
- 2.3.1 字典的結構
- 2.3.2 哈希算法
- 2.3.3 解決鍵沖突
- 2.3.4 rehash
- 2.3.5 字典的API
- 2.4 跳躍表
- 2.4.1 跳躍表的結構
- 2.4.2 跳躍表的API
- 2.5 整數集合
- 2.5.1 整數集合的結構
- 2.5.2 整數集合的API
- 2.6 壓縮列表
- 2.6.1 壓縮列表的結構
- 2.6.2 壓縮列表結點的結構
- 2.6.3 連鎖更新
- 2.6.4 壓縮列表API
- 2.7 對象
- 2.7.1 類型
- 2.7.2 編碼和底層實現
- 2.7.3 字符串對象
- 2.7.4 列表對象
- 2.7.5 哈希對象
- 2.7.6 集合對象
- 2.7.7 有序集合對象
- 2.7.8 類型檢查與命令多態
- 2.7.9 內存回收
- 2.7.10 對象共享
- 2.7.11 對象空轉時長
- 3 單機數據庫的實現
- 3.1 數據庫
- 3.1.1 服務端中的數據庫
- 3.1.2 切換數據庫
- 3.1.3 數據庫鍵空間
- 3.1.4 過期鍵的處理
- 3.1.5 數據庫通知
- 3.2 RDB持久化
- 操作系統
- 2021-01-08 Linux I/O 操作
- 2021-03-01 Linux 進程控制
- 2021-03-01 Linux 進程通信
- 2021-06-11 Linux 性能優化
- 2021-06-18 性能指標
- 2022-05-05 Android 系統源碼閱讀筆記
- Java基礎
- 2020-07-18 Java 前端編譯與優化
- 2020-07-28 Java 虛擬機類加載機制
- 2020-09-11 Java 語法規則
- 2020-09-28 Java 虛擬機字節碼執行引擎
- 2020-11-09 class 文件結構
- 2020-12-08 Java 內存模型
- 2021-09-06 Java 并發包
- 代碼性能
- 2020-12-03 Java 字符串代碼性能
- 2021-01-02 ASM 運行時增強技術
- 理解Unsafe
- Java 8
- 1 行為參數化
- 1.1 行為參數化的實現原理
- 1.2 Java 8中的行為參數化
- 1.3 行為參數化 - 排序
- 1.4 行為參數化 - 線程
- 1.5 泛型實現的行為參數化
- 1.6 小結
- 2 Lambda表達式
- 2.1 Lambda表達式的組成
- 2.2 函數式接口
- 2.2.1 Predicate
- 2.2.2 Consumer
- 2.2.3 Function
- 2.2.4 函數式接口列表
- 2.3 方法引用
- 2.3.1 方法引用的類別
- 2.3.2 構造函數引用
- 2.4 復合方法
- 2.4.1 Comparator復合
- 2.4.2 Predicate復合
- 2.4.3 Function復合
- 3 流處理
- 3.1 流簡介
- 3.1.1 流的定義
- 3.1.2 流的特點
- 3.2 流操作
- 3.2.1 中間操作
- 3.2.2 終端操作
- 3.3.3 構建流
- 3.3 流API
- 3.3.1 flatMap的用法
- 3.3.2 reduce的用法
- 3.4 collect操作
- 3.4.1 collect示例
- 3.4.2 Collector接口