Redis中,爲了更好地管理鏈表,定義了一個list的數據結構,做爲鏈表的封裝java
typedef struct listNode { // 前置節點 struct listNode *prev; // 後置節點 struct listNode *next; // 節點的值 void *value; } listNode;
typedef struct list { // 頭節點 listNode *head; // 尾節點 listNode *tail; // 鏈表中的節點數 unsigned int len; // 節點值複製函數 void *(*dup) (void *ptr); // 節點值釋放函數 void (*free) (void *ptr); // 節點值對比函數 int (*match) (void *ptr, void *key); } list;
Redis的鏈表的實現的主要特性:算法
a,評論系統數組
相似微博, 在看完一條微博以後,經常會評論一番,或者看看其餘人的吐槽。每條評論的記錄都是按照時間順序排序的。讀的時候也是這個順序。這時,隊列就是一個很好的存儲結構。每提交一次評論,都向list的末尾添加一個新的節點。安全
b,並行轉串行數據結構
用戶每時每刻均可能發出請求,並且請求的頻率常常變化。這時,後臺的程序不可能馬上響應每個用戶的請求,尤爲是請求特別佔資源的服務的時候(雙11的時候,404頁面?)。有什麼好的辦法來解決這個問題呢?須要一個排隊系統。根據用戶的請求時間,將用戶的請求放入隊列中,後臺程序依次從隊列中獲取任務,處理並將結果返回到結果隊列。函數
LPUSH key value [value ...] 從隊列的左邊入隊一個或多個元素,複雜度O(1)spa
RPUSHX key value 從隊列的右邊入隊一個元素,僅隊列存在時有效。當隊列不存在時,不進行任何操做。scala
LPUSHX key value 從隊列的左邊入隊一個元素,僅隊列存在時有效。當隊列不存在時,不進行任何操做。指針
LPOP key 從隊列的左邊出隊一個元素,複雜度O(1)。若是list爲空,則返回null。code
RPOP key 從隊列的右邊出隊一個元素,複雜度O(1)。若是list爲空,則返回null。
BLPOP key [key ...] timeout 刪除並得到該列表中的第一元素,或阻塞,直到有一個可用。
timeout表示等待的時間,單位是秒。當設爲0時,表示永遠阻塞,非0時,表示等待的最長時間
BRPOP key [key ...] timeout 刪除並得到該列表中的最後一個元素,或阻塞,直到有一個可用
RPOPLPUSH source destination
刪除列表中的最後一個元素,將其追加到另外一個列表。
這個命令能夠原子性地返回並刪除source對應的列表的最後一個元素(尾部元素),並將鈣元素放入destination對應的列表的第一個元素位置(列表頭部)。
使用這個模式的客戶端是易於擴展(scalable)且安全的(reliable),由於即便客戶端把接收到的消息丟失了, 這個消息依然存在於隊列中,等下次迭代到它的時候,由其餘客戶端進行處理。
BRPOPLPUSH source destination timeout
彈出一個列表的值,將它推到另外一個列表,並返回它;或阻塞,直到有一個可用
RPOPLPUSH的阻塞版本。timeout的單位是秒,當timeout爲0的時候,表示無限期阻塞。
LLEN key 得到隊列(List)的長度
LRANGE key start stop 從列表中獲取指定返回的元素.
負數表示從右向左數。超出範圍的下標不會產生錯誤:若是start>end,會獲得空列表,若是end超過隊尾,則Redis會將其當作列表的最後一個元素LINDEX key index 獲取一個元素,經過其索引列表
以前介紹的操做都是對list的兩端進行的,因此算法複雜度都只有O(1)。而這個操做是指定位置來進行的,每次操做,list都得找到對應的位置,所以算法複雜度爲O(N)。list的下表是從0開始的,index爲負的時候是從右向左數。-1表示最後一個元素。當下標超出的時候,會返回nul。因此不用像操做數組同樣擔憂範圍越界的狀況。LSET key index value 設置隊列裏面一個元素的值 當index越界的時候會報異常
LREM key count value 從列表中刪除元素
該命令用於從key對應的list中,移除前count次出現 的值爲value的元素。count參數有三種狀況:
count > 0: 表示從頭向尾(左到右)移除值爲value的元素。
count < 0: 表示從尾向頭(右向左)移除值爲value的元素。
count = 0: 表示移除全部值爲value的元素。
LTRIM key start stop 修剪到指定範圍內的清單
這個命令和LRANGE十分類似,LRANGE會將指定範圍的元素返回給客戶端,而LTRIM會對list進行修剪,使其只包含指定範圍的元素。start和stop表示範圍。
超出範圍的下標不會產生錯誤:若是start>end,會獲得空列表,若是end超過隊尾,則Redis會將其當作列表的最後一個元素。
LINSERT key BEFORE|AFTER pivot value 在列表中的另外一個元素以前或以後插入一個元素
該命令將value插入值key對應的列表的基準值pivot的前面或是後面。
當key不存在時,這個list被視爲空列表,任何操做都不會發生。
當key存在,但保存的不是list,則會報error。
該命令會返回修改以後的list的長度,若是找不到pivot,則會返回-1。