複習電商筆記-27-Redis高階中的list結構
Redis高階中的list結構
一個列表最多可以包含232-1個元素(4294967295,每個表超過40億個元素)
問題
Redis的list型別其實就是一個每個子元素都是string型別的雙向連結串列。可以通過push,pop操作從連結串列的頭部或者尾部新增刪除元素。這使得list既可以用作棧,也可以用作佇列。
有意思的是list的pop操作還有阻塞版本的,當我們[lr]pop一個list物件時,如果list是空,或者不存在,會立即返回nil。但是阻塞版本的b[lr]pop可以則可以阻塞,當然可以加超時時間,超時後也會返回nil。為什麼要阻塞版本的pop呢,主要是為了避免輪詢。舉個簡單的例子如果我們用list來實現一個工作佇列。執行任務的thread可以呼叫阻塞版本的pop去獲取任務這樣就可以避免輪詢去檢查是否有任務存在。當任務來時候工作執行緒可以
lpush
在key對應list的頭部新增字串元素
redis 127.0.0.1:6379> lpush mylist "world"
(integer) 1
redis 127.0.0.1:6379> lpush mylist "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>
rpush
在key對應list的尾部新增字串元素
redis 127.0.0.1:6379> rpush mylist2 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist2 "world"
(integer) 2
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>
檢視list
redis 127.0.0.1:6379> lrange mylist3 0 -1
del
redis 127.0.0.1:6379> del mylist
linsert
在key對應list的特定位置之前或之後新增字串元素
redis 127.0.0.1:6379> rpush mylist3 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist3 "world"
(integer) 2
redis 127.0.0.1:6379> linsert mylist3 before "world" "there"
(integer) 3
redis 127.0.0.1:6379> lrange mylist3 0 -1
1) "hello"
2) "there"
3) "world"
redis 127.0.0.1:6379>
lset
設定list中指定下標的元素值
redis 127.0.0.1:6379> rpush mylist4 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist4 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist4 "three"
(integer) 3
redis 127.0.0.1:6379> lset mylist4 0 "four"
OK
redis 127.0.0.1:6379> lset mylist4 -2 "five"
OK
redis 127.0.0.1:6379> lrange mylist4 0 -1
1) "four"
2) "five"
3) "three"
redis 127.0.0.1:6379>
lrem
從key對應list中刪除count個和value相同的元素,count>0時,按從頭到尾的順序刪除
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist5 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist5 2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "foo"
2) "hello"
redis 127.0.0.1:6379>
count<0時,按從尾到頭的順序刪除
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist6 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist6 -2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "foo"
redis 127.0.0.1:6379>
count=0時,刪除全部
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist7 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist7 0 "hello"
(integer) 3
redis 127.0.0.1:6379> lrange mylist7 0 -1
1) "foo"
redis 127.0.0.1:6379>
ltrim
保留指定key 的值範圍內的資料
redis 127.0.0.1:6379> rpush mylist8 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist8 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist8 "three"
(integer) 3
redis 127.0.0.1:6379> rpush mylist8 "four"
(integer) 4
redis 127.0.0.1:6379> ltrim mylist8 1 -1
OK
redis 127.0.0.1:6379> lrange mylist8 0 -1
1) "two"
2) "three"
3) "four"
redis 127.0.0.1:6379>
lpop
從list的頭部刪除元素,並返回刪除元素
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> lpop mylist
"hello"
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "world"
redis 127.0.0.1:6379>
rpop
從list的尾部刪除元素,並返回刪除元素:
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> rpop mylist2
"world"
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
redis 127.0.0.1:6379>
llen
返回key對應list的長度:
redis 127.0.0.1:6379> llen mylist5
(integer) 2
redis 127.0.0.1:6379>
index
返回名稱為key的list中index位置的元素:
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
2) "foo"
redis 127.0.0.1:6379> lindex mylist5 0
"three"
redis 127.0.0.1:6379> lindex mylist5 1
"foo"
redis 127.0.0.1:6379>
rpoplpush
從第一個list的尾部移除元素並新增到第二個list的頭部,最後返回被移除的元素值,整個操作是原子的.如果第一個list是空或者不存在返回nil:
拓展:利用連結串列形成安全訊息佇列
RPOPLPUSH命令實現安全訊息佇列。Redis連結串列經常會被用於訊息佇列的服務,以完成多程式之間的訊息交換。假設一個應用程式正在執行LPUSH操作向連結串列中新增新的元素,我們通常將這樣的程式稱之為"生產者(Producer)",而另外一個應用程式正在執行RPOP操作從連結串列中取出元素,我們稱這樣的程式為"消費者(Consumer)"。如果此時,消費者程式在取出訊息元素後立刻崩潰,由於該訊息已經被取出且沒有被正常處理,那麼我們就可以認為該訊息已經丟失,由此可能會導致業務資料丟失,或業務狀態的不一致等現象的發生。然而通過使用RPOPLPUSH命令,消費者程式在從主訊息佇列中取出訊息之後再將其插入到備份佇列中,直到消費者程式完成正常的處理邏輯後再將該訊息從備份佇列中刪除。同時我們還可以提供一個守護程序,當發現備份佇列中的訊息過期時,可以重新將其再放回到主訊息佇列中,以便其它的消費者程式繼續處理。