前言
在 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;
複製程式碼
在列表中的每個節點的資料結構都是一個雙向連結串列結構,在 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;
複製程式碼
- head 指向頭部節點,獲取的時間複雜度為O(1)
- tail 指向尾部節點,獲取的時間複雜度為O(1)
- len 儲存著列表的長度資訊,獲取的時間複雜度為O(1)
- dup 函式用於複製連結串列節點所儲存的值
- free 函式用於釋放連結串列節點所儲存的值
- match 函式則用於對比連結串列節點所儲存的值和另一個輸入值是否相等。
實際業務中 List 的使用場景
- 一個是粉絲關注列表,收藏列表等,這種的業務需求是比較頻繁和常見的。
- 作為訊息佇列的使用,雖然有RabbitMQ、Kafka等訊息佇列,List也是可以當為輕量級別的訊息佇列來使用的。
- 如果僅僅是把 list 當做一個容器來儲存資料的話,那麼用 Hash 這個字串就可以了,Hash 使用的效果會更好。