Redis
List
基本的數據類型,列表,可以實現 棧 隊列
所有的list都以L開頭
### PUSH ###
# LPUSH key element [element ...] 可同時push多個值
127.0.0.1:6379> LPUSH list one #插入列表的頭部 棧頂
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LRANGE list 0 -1 # 查看列表的全部元素 LRANGE key start stop
1) "two"
2) "one"
127.0.0.1:6379> LRANGE list 0 1
1) "two"
2) "one"
127.0.0.1:6379> RPUSH list right #插到隊列的尾部 棧的底部
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
3) "right"
### POP ###
127.0.0.1:6379> lpop list #移除列首 棧頂
"two"
127.0.0.1:6379> rpop list #移除列尾 棧底
"right"
### lindex key index###
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lindex list 0 #類似數組從左到右 0 -> max 第一個元素是0
"three"
127.0.0.1:6379> lindex list 1
"two"
### Llen key start stop查看長度 ###
127.0.0.1:6379> lpush list one
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> llen list #返回列表的長度
(integer) 3
### Lrem key count element 移除key中count個數指定元素 ###
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "three"
4) "two"
127.0.0.1:6379> lrem list 1 two
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
### ltrim key start stop 截斷###
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
### rpoplpush source destination 移除列表的最後一個元素放入新列表中###
127.0.0.1:6379> lpush list hello
(integer) 1
127.0.0.1:6379> lpush list hello1
(integer) 2
127.0.0.1:6379> lpush list hello2
(integer) 3
127.0.0.1:6379> lpush list hello3
(integer) 4
127.0.0.1:6379> rpoplpush list list2
"hello"
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "hello2"
3) "hello1"
127.0.0.1:6379> lrange list2 0 -1
1) "hello"
### lset key index element ###
# 將列表中指定下標的值更新爲另一個值
# 如果不存在列表就會報錯 如果存在就會更新當前下標值
### linsert key BEFORE|AFTER pivot element
# 將world插入在item之前
127.0.0.1:6379> linsert list before item world
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "world"
2) "item"
3) "hello2"
4) "hello1"
# 將world插入在item之後
127.0.0.1:6379> linsert list after item world
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "world"
2) "item"
3) "world"
4) "hello2"
5) "hello1"
小結
-
實際上是一個雙向鏈表,before node after left right都可以插入
-
如果key不存在,創建新鏈表
-
如果key存在,新增內容
-
如果移除了所有值,空鏈表,也代表不存在
-
在兩邊插入或者改動值,效率高,中間元素效率低
-
如果用LRANGE來獲取數據,起始位置越大,速度越慢
list底層數據結構
127.0.0.1:6379> object encoding list
"quicklist"
Redis自己構件了鏈表的實現(c語言)
typedef struct listNode{
//前置節點
struct listNode *prev;
//後置節點
struct listNode *next;
//節點的值
void *value;
}listNode
typedef struct list{
//表頭節點
listNode *head;
//表尾節點
listNode *tail;
//鏈表所包含的節點數量
unsigned long len;
//節點值複製函數
void (*free) (void *ptr);
//節點值釋放函數
void (*free) (void *ptr);
//節點值對比函數
int (*match) (void *ptr,void *key);
}list;
Redis鏈表特性:
①、雙端:鏈表具有前置節點和後置節點的引用,獲取這兩個節點時間複雜度都爲O(1)。
②、無環:表頭節點的 prev 指針和表尾節點的 next 指針都指向 NULL,對鏈表的訪問都是以 NULL 結束。
③、帶鏈表長度計數器:通過 len 屬性獲取鏈表長度的時間複雜度爲 O(1)。
④、多態:鏈表節點使用 void* 指針來保存節點值,可以保存各種不同類型的值。