(三分鐘系列)詳解Redis中列表(List)的使用方法和內部結構

spacedong發表於2018-09-11

前言

在 Redis 中的列表是一個非常靈活的資料結構,提供了非常多的操作 API ,可以根據 API 的組合來滿足需要的業務場景。

目錄

  • Redis列表( List )的常用方法及演示
  • Redis中列表( List )內部結構和原始碼解析
    • 內部結構
    • 原始碼解析
  • 實際業務中列表( List )的使用場景

列表常用方法

1. 左右邊插入鍵值對

//左邊插入
redis 127.0.0.1:6379> LPUSH spacedong test1
"1"

//右邊插入
redis 127.0.0.1:6379> RPUSH spacedong test2
"2"

//左邊彈出
127.0.0.1:6379:3>LPOP spacedong
"test1"

//右邊彈出
127.0.0.1:6379:3>RPOP spacedong
"test2"
複製程式碼

2. 獲取指定的區域的元素

127.0.0.1:6379:3>LRANGE spacedong 0 2
 1)  "test1"
 2)  "test2"
複製程式碼

3. 通過索引獲取列表中的元素

127.0.0.1:6379:3>LINDEX spacedong 1
"test2"
複製程式碼

4. 修改特定位置的值

127.0.0.1:6379:3>LINDEX spacedong 1
"test2"
127.0.0.1:6379:3>LSET spacedong 1 test3
"OK"
127.0.0.1:6379:3>LINDEX spacedong 1
"test3"
複製程式碼

5. 阻塞佇列的實現

  • BRPOP key timeout , timeout 如果指定為0,則客戶端會一直等待下去,如果 timeout 指定多少秒,那麼就會多少秒後返回。返回的第一個值是key,返回的第二個值是具體的元素。如果該key沒有具體的元素時,返回為空。
//插入元素到key中
127.0.0.1:6379:3>LPUSH spacedong test1
"1"

//彈出key中的元素
127.0.0.1:6379:3>BRPOP spacedong 3
 1)  "spacedong"
 2)  "test3"
複製程式碼

列表( List )的內部結構和原始碼解析

  • 列表的資料結構
typedef struct listNode {

    // 前置節點
    struct listNode *prev;

    // 後置節點
    struct listNode *next;

    // 節點的值
    void *value;

} listNode;
複製程式碼

image
在列表中的每個節點的資料結構都是一個雙向連結串列結構,在 Redis 中則是實現了自己的連結串列結構,如下圖所示

typedef struct list {

    // 表頭節點
    listNode *head;

    // 表尾節點
    listNode *tail;

    // 連結串列所包含的節點數量
    unsigned long len;

    // 節點值複製函式
    void *(*dup)(void *ptr);

    // 節點值釋放函式
    void (*free)(void *ptr);

    // 節點值對比函式
    int (*match)(void *ptr, void *key);

} list;
複製程式碼

image

  • head 指向頭部節點,獲取的時間複雜度為O(1)
  • tail 指向尾部節點,獲取的時間複雜度為O(1)
  • len 儲存著列表的長度資訊,獲取的時間複雜度為O(1)
  • dup 函式用於複製連結串列節點所儲存的值
  • free 函式用於釋放連結串列節點所儲存的值
  • match 函式則用於對比連結串列節點所儲存的值和另一個輸入值是否相等。

實際業務中 List 的使用場景

  • 一個是粉絲關注列表,收藏列表等,這種的業務需求是比較頻繁和常見的。
  • 作為訊息佇列的使用,雖然有RabbitMQ、Kafka等訊息佇列,List也是可以當為輕量級別的訊息佇列來使用的。
  • 如果僅僅是把 list 當做一個容器來儲存資料的話,那麼用 Hash 這個字串就可以了,Hash 使用的效果會更好。

相關文章