Redis - list

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的鏈表的實現的主要特性:算法

  1. 雙端:鏈表節點都有prev和next指針,獲取節點的前置節點和後置節點的算法複雜度都爲O(1)。
  2. 無環:list的第一個節點(頭節點)的prev和最後一個節點(尾節點)的next都指向NULL。
  3. 帶表頭指針和表尾指針:經過list的head和tail兩個指針,能夠隨意的從鏈表的頭和尾進行操做。
  4. 帶鏈表長度計數器:能夠經過len成員來獲取鏈表的節點的個數,複雜度O(1)。
  5. 多態:鏈表使用void *指針來保存value,而且能夠經過dup,free,match來操控節點的value值,所以,該鏈表能夠保存任意類型的值。

操做

  1. RPUSH key value [value ...] 
    從隊列的右邊入隊一個元素或多個元素,複雜度O(1) ; 將全部指定的值插入存於key的列表的尾部(從右側插入)。
    若是key不存在,那麼PUSH以前,會先自動建立一個空的列表。若是key對應的值不是一個list的話,則會返回一個錯誤。若是同時push多個值的話,值會依次從左到右PUSH從尾部進入list。

    a,評論系統數組

    相似微博, 在看完一條微博以後,經常會評論一番,或者看看其餘人的吐槽。每條評論的記錄都是按照時間順序排序的。讀的時候也是這個順序。這時,隊列就是一個很好的存儲結構。每提交一次評論,都向list的末尾添加一個新的節點。安全

    b,並行轉串行數據結構

    用戶每時每刻均可能發出請求,並且請求的頻率常常變化。這時,後臺的程序不可能馬上響應每個用戶的請求,尤爲是請求特別佔資源的服務的時候(雙11的時候,404頁面?)。有什麼好的辦法來解決這個問題呢?須要一個排隊系統。根據用戶的請求時間,將用戶的請求放入隊列中,後臺程序依次從隊列中獲取任務,處理並將結果返回到結果隊列。函數

  2. LPUSH key value [value ...] 從隊列的左邊入隊一個或多個元素,複雜度O(1)spa

  3. RPUSHX key value 從隊列的右邊入隊一個元素,僅隊列存在時有效。當隊列不存在時,不進行任何操做。scala

  4. LPUSHX key value 從隊列的左邊入隊一個元素,僅隊列存在時有效。當隊列不存在時,不進行任何操做。指針

  5. LPOP key 從隊列的左邊出隊一個元素,複雜度O(1)。若是list爲空,則返回null。code

  6. RPOP key 從隊列的右邊出隊一個元素,複雜度O(1)。若是list爲空,則返回null。

  7. BLPOP key [key ...] timeout 刪除並得到該列表中的第一元素,或阻塞,直到有一個可用。
    timeout表示等待的時間,單位是秒。當設爲0時,表示永遠阻塞,非0時,表示等待的最長時間

  8. BRPOP key [key ...] timeout 刪除並得到該列表中的最後一個元素,或阻塞,直到有一個可用

  9. RPOPLPUSH source destination 

    刪除列表中的最後一個元素,將其追加到另外一個列表。

    這個命令能夠原子性地返回並刪除source對應的列表的最後一個元素(尾部元素),並將鈣元素放入destination對應的列表的第一個元素位置(列表頭部)。

    使用這個模式的客戶端是易於擴展(scalable)且安全的(reliable),由於即便客戶端把接收到的消息丟失了, 這個消息依然存在於隊列中,等下次迭代到它的時候,由其餘客戶端進行處理。

  10. BRPOPLPUSH source destination timeout 

    彈出一個列表的值,將它推到另外一個列表,並返回它;或阻塞,直到有一個可用

    RPOPLPUSH的阻塞版本。timeout的單位是秒,當timeout爲0的時候,表示無限期阻塞。

  11. LLEN key 得到隊列(List)的長度

  12. LRANGE key start stop 從列表中獲取指定返回的元素.

    負數表示從右向左數。超出範圍的下標不會產生錯誤:若是start>end,會獲得空列表,若是end超過隊尾,則Redis會將其當作列表的最後一個元素
  13. LINDEX key index  獲取一個元素,經過其索引列表

    以前介紹的操做都是對list的兩端進行的,因此算法複雜度都只有O(1)。而這個操做是指定位置來進行的,每次操做,list都得找到對應的位置,所以算法複雜度爲O(N)。list的下表是從0開始的,index爲負的時候是從右向左數。-1表示最後一個元素。當下標超出的時候,會返回nul。因此不用像操做數組同樣擔憂範圍越界的狀況。
  14. LSET key index value 設置隊列裏面一個元素的值 當index越界的時候會報異常

  15. LREM key count value  從列表中刪除元素

    該命令用於從key對應的list中,移除前count次出現 的值爲value的元素。count參數有三種狀況:

    count > 0: 表示從頭向尾(左到右)移除值爲value的元素。

    count < 0: 表示從尾向頭(右向左)移除值爲value的元素。

    count = 0: 表示移除全部值爲value的元素。

  16. LTRIM key start stop  修剪到指定範圍內的清單

    這個命令和LRANGE十分類似,LRANGE會將指定範圍的元素返回給客戶端,而LTRIM會對list進行修剪,使其只包含指定範圍的元素。start和stop表示範圍。

    超出範圍的下標不會產生錯誤:若是start>end,會獲得空列表,若是end超過隊尾,則Redis會將其當作列表的最後一個元素。

  17. LINSERT key BEFORE|AFTER pivot value 在列表中的另外一個元素以前或以後插入一個元素

    該命令將value插入值key對應的列表的基準值pivot的前面或是後面。

    當key不存在時,這個list被視爲空列表,任何操做都不會發生。

    當key存在,但保存的不是list,則會報error。

    該命令會返回修改以後的list的長度,若是找不到pivot,則會返回-1。

相關文章
相關標籤/搜索