簡簡單單說下Redis 有序集合

簡簡單單說下Redis 有序集合

什麼是redis 有序集合

redis有5種數據類型,包括:redis

  1. string 字符串:能夠爲整形、浮點型和字符串,統稱爲元素。
  2. list 列表:能夠做爲隊列使用。
  3. set 集合: 一個集合內,全部元素各部相同。
  4. hash hash散列值: 即字典,key值惟一。
  5. sortedSet 有序集合。

和集合同樣,有序集合也是 string 類型元素的集合,且元素不容許重複。不一樣的是,有序集合的每一個元素都會關聯一個 double 類型的分數(score)。redis 經過分數來爲集合中的成員進行從小到大的排序。ide

有序集合的成員是惟一的,但分數卻能夠重複。性能

有序集合查找任意數據的時間複雜度是O(1),插入、刪除操做的時間複雜度是O(logN)。設計

因爲有序集合能夠根據分數對元素進行排序,所以有序集合可用於排行榜、學生成績排名等用途。3d

有序集合的底層實現

出於對性能的考慮,有序集合底層有兩類實現:指針

  1. 當有序集合保存的元素數量小於128個,而且全部元素的長度都小於64字節時,有序集合對象使用ziplist實現。
  2. 當不知足上述條件時,有序集合對象使用skiplist+字典實現。

說一說ziplist

ziplist(壓縮列表)實現的有序集合對象中,每一個元素是用須要使用兩個連續的壓縮列表節點保存,第一個節點保存元素的成員,第二個節點保存元素的分值,分值爲double 類型。對象

壓縮列表內的元素,會按照分值,從小到大排序。若是分值相同,則按照元素成員的大小,從小到大排序。大體以下圖所示:blog

8b3161c5648d557657c01e543ded662f.png

說一說skiplist

skiplist(跳躍表)採用了鏈表加多級索引的結構。它使用了空間換時間的設計思路,在存儲時創建了不少級索引。使得在跳躍表中查找、插入和刪除的時間複雜度都是O(logN)。排序

它的實現大體以下圖所示:索引

3fec7869a6eb7c70d17f9c53f6ab2c87.png

  1. 最下一層是鏈表,有序的保存全部的數據。
  2. 原始鏈表以上,都爲索引層。在每級索引的基礎上,每隔幾個節點抽出一個節點,造成更上一級索引。
  3. 每一個節點不直接保存數據,而是保存指針,這樣能減小對空間的消耗。
  4. 當查找某條數據時,會先從上往下在索引層遍歷,找到該數據所在的索引範圍。經過索引層節點的指針,不斷降低到下一層,直到原始鏈表這一層。繼續遍歷,直到找到該節點,或者經過邏輯判斷該節點不存在。
  5. 當插入或刪除時,也會先查找到位置,插入到鏈表中或從鏈表中刪除,並動態更新索引層,維護索引與原始鏈表大小之間的平衡。例如鏈表中結點多了,索引結點就相應地增長一些,避免查找,插入,刪除操做性能降低。

爲何有序集合須要同時使用跳躍表和字典來實現?

有序列表使用skiplist(跳躍表)+字典實現,是爲了保證查找和範圍型操做(ZRANK、ZRANGE等)都能儘量快的執行。

例如只使用跳躍表,查找單個成員,複雜度爲O(logN)。

例如只使用字典,因爲字典是無序的,範圍型的操做,會須要使用至少O(NlogN)時間複雜度和額外的O(N)空間對數據排序,再進行範圍型操做。

而同時使用跳躍表+字典,查找單個成員,能夠直接在字典中查找,複雜度爲O(1),範圍型操做則在跳躍表中操做,複雜度爲O(lngN)。

相關文章
相關標籤/搜索