最近在精進學習Redis,邊學邊寫
java
先贊後讀,養成習慣python
注意它是鏈表而不是數組。這意味着 list 的插入和刪除操做很是快,時間複雜度爲 O(1),可是索引定位很慢,時間複雜度爲 O(n)
另外當列表彈出了最後一個元素以後,該數據結構自動被刪除,內存被回收。
複製代碼
# 進入隊列
> rpush books python java golang
(integer) 3
# 隊列長度
> llen books
(integer) 3
# 取出隊列
> lpop books
"python"
> lpop books
"java"
> lpop books
"golang"
> lpop books
(nil)
複製代碼
# 入棧
> rpush books python java golang
(integer) 3
# 出棧
> rpop books
"golang"
> rpop books
"java"
> rpop books
"python"
> rpop books
(nil)
複製代碼
lindex 至關於 Java 鏈表的get(int index)方法,它須要對鏈表進行遍歷,性能隨着參數index增大而變差。golang
> rpush books python java golang
(integer) 3
> lindex books 1 # O(n) 慎用
"java"
> lrange books 0 -1 # 獲取全部元素,O(n) 慎用
1) "python"
2) "java"
3) "golang"
> ltrim books 1 0 # O(n) 慎用 這實際上是清空了整個列表,由於區間範圍長度爲負
OK
> llen books
(integer) 0
複製代碼
ltrim 和字面意思不太同樣,與其說去除
不如說保留
。redis
由於 ltrim 兩個參數start_index和end_index定義了一個區間內的值將被保留下來。
這使它很是適合實現一個定長的鏈表shell
鏈表
用來作異步隊列
鏈表
經常使用來作異步隊列
使用將須要延後
處理的任務結構體序列化(JSON)
成字符串塞進 Redis 的列表數組
另外一個線程從這個列表中輪詢數據進行處理。安全
lpush
+ lpop
= stack 先進後出的棧bash
lpush
+ rpop
= queue 先進先出的隊列服務器
lpush
+ ltrim
= capped collection 有限集合數據結構
lpush
+ brpop
= message queue 消息隊列
消息丟失
問題通常藉助List來實現消息隊列:
但這種方式實現的隊列是不安全
的。
由於RPOP(BRPOP)命令的特性:
移除
list的隊尾元素(消息)並返回給客戶端。這時該元素只存在
於客戶端的上下文中,redis服務器中沒有
這個元素.崩潰
了,那麼這個元素就永遠丟失了。這種狀況致使:客戶端雖然成功收到了消息,可是卻沒有處理它
。那怎麼來實現一個更安全的隊列呢? 能夠試試redis的RPOPLPUSH
(或者其阻塞版本的 BRPOPLPUSH
)命令。
具體是操做是:
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> RPOPLPUSH mylist myotherlist
"three"
redis> LRANGE mylist 0 -1
1) "one"
2) "two"
redis> LRANGE myotherlist 0 -1
1) "three"
redis>
複製代碼
這種方法存在兩個問題,
lrem a 0 "元素"
函數找到並刪除消息,另外啓動的那個專門處理第二個隊列的client面對的隊列中的信息數量必須很小,若是很大client處理不過來又不能使用併發,由於使用併發必須將消息pop出隊列2,若是pop出隊列2,那就又回到了咱們原本要繞開的問題。因此折騰試試,發現redislist
所以對於一致性要求高的場景,隊列建議使用Redis 5的 Stream 或者 RocketMQ。 目前還沒發現特別適合redis list使用場景,有想到的小夥伴留言交流下❤️