Redis中支援的資料結構比Memcached要多的多啦,如基本的字串、雜湊表、列表、集合、可排序集,在這些基本資料結構上也提供了針對該資料結構的各種操作,這也是Redis之所以流行起來的一個重要原因,當然Redis能夠流行起來的原因,遠遠不只這一個,如支援高並發的讀寫、資料的持久化、高效的記憶體管理及淘汰機制...
從Redis的git提交曆史中,可以查到,2009/10/24在1.050版本,Redis開始支援可排序集,在該版本中,只提供了一條命令zadd,宏定義如下所示:
1 {"zadd",zaddCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
那麼什麼是可排序集呢? 從Redis 1.0開始就給我們提供了集合(Set)這種資料結構,集合就跟數學上的集合概念是一個道理【無序性,確定性,互異性】,集合裡的元素無法保證元素的順序,而業務上的需求,可能不止是一個集合,而且還要求能夠快速地對集合元素進行排序,於是乎,Redis中提供了可排序集這麼一種資料結構,似乎也是合情合理,無非就是在集合的基礎上增加了排序功能,也許有人會問,Redis中不是有Sort命令嘛,下面的操作不也是同樣可以達到對無序集的排序功能嘛,是的,是可以,但是在這裡我們一直強調的是快速這兩個字,而Sort命令的時間複雜度為O(N+M*Log(M)),可排序集擷取一定範圍內元素的時間複雜度為O(log(N) + M)
root@bjpengpeng-VirtualBox:/home/bjpengpeng/redis-3.0.1/src# ./redis-cli 127.0.0.1:6379> sort set1) "1"2) "2"3) "3"4) "5"127.0.0.1:6379> sort set desc1) "5"2) "3"3) "2"4) "1"127.0.0.1:6379>
在瞭解可排序集是如何?之前,需要瞭解一種資料結構跳錶(Skip List),跳錶與AVL、紅/黑樹狀結構...等相比,資料結構簡單,演算法易懂,但查詢的時間複雜度與平衡二叉樹/紅/黑樹狀結構相當,跳錶的基本結構如下圖所示
上圖中整個跳錶結構存放了4個元素5->10->20->30,圖中的紅色線表示尋找元素30時,走的尋找路線,從Head指標數組裡最頂層的指標所指的20開始比較,與普通的鏈表尋找相比,跳錶的查詢可以跳躍元素,上圖中查詢30,發現30比20大,則尋找就是20開始,而普通鏈表的查詢必須一個元素一個元素的比較,時間複雜度為O(n)
有了上圖所示的跳錶基本結構,再看看如何向跳錶中插入元素,向跳錶中插入元素,由於元素所在層級的隨機性,平均起來也是O(logn),說白了,就是尋找元素應該插入在什麼位置,然後就是普通的移動指標問題,再想想往有序單鏈表的插入操作吧,時間複雜度是不是也是O(n),下圖所示是往跳錶中插入元素28的過程,圖中紅色線表示尋找插入位置的過程,綠色線表示進行指標的移動,將該元素插入
有了跳錶的尋找及插入那麼就看看在跳錶中如何刪除元素吧,跳錶中刪除元素的個程,尋找要刪除的元素,找到後,進行指標的移動,過程如下圖所示,刪除元素30
有了上面的跳錶基本結構圖及原理,自已設計及實現跳錶吧,這樣當看到Redis裡面的跳錶結構時我們會更加熟悉,更容易理解些,【下面是對Redis中的跳錶資料結構及相關代碼進行精減後形成的可運行代碼】,首先定義跳錶的基本資料結構如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include<stdio.h> |