redis系列:通過隊列案例學習list命令

前言

這一篇文章將講述Redis中的list類型命令,同樣也是通過demo來講述,其他部分這裏就不在贅述了。

項目Github地址:https://github.com/rainbowda/...

案例

demo功能是隊列,整個demo的大致頁面如下。左邊是存儲到Redis中的數據,右邊是從Redis中彈出的數據。

clipboard.png

準備工作

首先定義一個存儲list的key

clipboard.png

隊列的key就用list:1

redis操作對象

clipboard.png

list在Redis中的結構可以看下圖(圖片來源於Redis in Action)。

clipboard.png

插入數據

頭部插入

命令介紹

clipboard.png

接下來看看demo中頭部插入的功能,點擊下圖中頭部插入按鈕,然後在彈出框中填入數字0,點擊提交後整個頭部插入流程結束。可以看到左邊的隊列數據出現了一條{"data":"0"} 數據,在數據{"data":"1"} 上面。

clipboard.png

來看看後臺的方法

clipboard.png

如果需要在Redis中操作,可以敲下面的命令

clipboard.png

尾部插入

命令介紹

clipboard.png

接下來看看demo中尾部插入的功能,點擊下圖中尾部插入按鈕,然後在彈出框中填入數字11,點擊提交後整個新增流程結束。可以看到左邊的隊列數據出現了一條{"data":"11"} 數據,在數據{"data":"10"}下面。

clipboard.png

來看看後臺的方法

clipboard.png

如果需要在Redis中操作,可以敲下面的命令

clipboard.png

列表查詢

命令介紹

同樣先看看相關的獲取值命令

clipboard.png

後臺查詢方法,將新增的內容查詢出來

clipboard.png

數據彈出

頭部彈出

clipboard.png

接下來看看頭部彈出的功能,點擊下圖中頭部彈出按鈕,可以看到左邊的隊列頂部數據減少了,在右邊彈出的數據出現了左邊隊列數據消失的數據。

clipboard.png

來看看後臺的方法

clipboard.png

如果需要在Redis中操作,可以敲下面的命令

clipboard.png

尾部彈出

clipboard.png

接下來看看尾部彈出的功能,點擊下圖中尾部彈出按鈕,可以看到左邊的隊列尾部數據減少了,在右邊彈出的數據出現了左邊隊列數據消失的數據。

clipboard.png

來看看後臺的方法

clipboard.png

如果需要在Redis中操作,可以敲下面的命令

clipboard.png

其他命令

clipboard.png

RPOPLPUSH和BRPOPLPUSH

這兩個命令作用其實是相同的,只不過BRPOPLPUSH是阻塞的,當沒有數據時,會一直阻塞,直到有數據。

在Redis官方文檔中,用RPOPLPUSH命令舉了兩個例子,一個是Reliable queue(安全的隊列 ),另一個是Circular list(循環列表)。

Reliable queue(安全的隊列 )

Redis通常都被用做一個處理各種後臺工作或消息任務的消息服務器。 一個簡單的隊列模式就是:生產者把消息放入一個列表中,等待消息的消費者用 RPOP 命令(用輪詢方式), 或者用 BRPOP 命令(如果客戶端使用阻塞操作會更好)來得到這個消息。

然而,因爲消息有可能會丟失,所以這種隊列並是不安全的。例如,當接收到消息後,出現了網絡問題或者消費者端崩潰了, 那麼這個消息就丟失了。

RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH)
提供了一種方法來避免這個問題:消費者端取到消息的同時把該消息放入一個正在處理中的列表。 當消息被處理了之後,該命令會使用 LREM
命令來移除正在處理中列表中的對應消息。

另外,可以添加一個客戶端來監控這個正在處理中列表,如果有某些消息已經在這個列表中存在很長時間了(即超過一定的處理時限),
那麼這個客戶端會把這些超時消息重新加入到隊列中。

翻譯來自 http://www.redis.cn/commands/...

Circular list(循環列表)

RPOPLPUSH 命令的 source 和 destination 是相同的話, 那麼客戶端在訪問一個擁有n個元素的列表時,可以在 O(N) 時間裏一個接一個獲取列表元素, 而不用像 LRANGE 那樣需要把整個列表從服務器端傳送到客戶端。

上面這種模式即使在以下兩種情況下照樣能很好地工作:
有多個客戶端同時對同一個列表進行旋轉(rotating):它們會取得不同的元素,直到列表裏所有元素都被訪問過,又從頭開始這個操作。
有其他客戶端在往列表末端加入新的元素。

這個模式讓我們可以很容易地實現這樣一個系統:有 N 個客戶端,需要連續不斷地對一批元素進行處理,而且處理的過程必須儘可能地快。
一個典型的例子就是服務器上的監控程序:它們需要在儘可能短的時間內,並行地檢查一批網站,確保它們的可訪問性。

值得注意的是,使用這個模式的客戶端是易於擴展(scalable)且安全的(reliable),因爲即使客戶端把接收到的消息丟失了,
這個消息依然存在於隊列中,等下次迭代到它的時候,由其他客戶端進行處理。

翻譯來自 http://www.redis.cn/commands/...

案例-約瑟夫問題

約瑟夫問題(有時也稱爲約瑟夫斯置換),是一個出現在計算機科學和數學中的問題。在計算機編程的算法中,類似問題又稱爲約瑟夫環。

人們站在一個等待被處決的圈子裏。 計數從圓圈中的指定點開始,並沿指定方向圍繞圓圈進行。 在跳過指定數量的人之後,執行下一個人。
對剩下的人重複該過程,從下一個人開始,朝同一方向跳過相同數量的人,直到只剩下一個人,並被釋放。

問題即,給定人數、起點、方向和要跳過的數字,選擇初始圓圈中的位置以避免被處決。

來自維基百科
https://zh.wikipedia.org/wiki...

clipboard.png

思路

定義一個list key爲josephus,利用

clipboard.png

命令來構造循環鏈表,每當數到3時,使用rpop

clipboard.png

命令彈出

代碼實現

clipboard.png

整個代碼步驟如下

  1. 先是模擬有41個人(向redis中key爲josephus的list添加41個數據)
  2. 定義索引index
  3. 循環判斷key爲josephus的數據長度是否大於0
  4. 當索引index爲3時,調用Redis的rpop命令彈出對應的數據。索引index不爲3時,調用RPOPLPUSH命令,將對應的數據放到隊列頭部
  5. 索引index加1

運行結果有點長,這裏只截圖最後一部分的結果,如下

clipboard.png

約瑟夫問題代碼請點擊JosephusProblem.java

建議學習的人最好每個命令都去敲下,加深印象。下面詩句送給你們。

紙上得來終覺淺,絕知此事要躬行。————出自《冬夜讀書示子聿》

本文作者: 勿妄

閱讀原文

本文爲雲棲社區原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章