這一篇文章將講述Redis中的list類型命令,同樣也是通過demo來講述,其他部分這里就不在贅述了。
成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)提供從項(xiàng)目策劃、軟件開發(fā),軟件安全維護(hù)、網(wǎng)站優(yōu)化(SEO)、網(wǎng)站分析、效果評(píng)估等整套的建站服務(wù),主營(yíng)業(yè)務(wù)為做網(wǎng)站、成都網(wǎng)站建設(shè),成都app軟件開發(fā)公司以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。成都創(chuàng)新互聯(lián)公司深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!項(xiàng)目Github地址: https://github.com/rainbowda/learnWay/tree/master/learnRedis/case-list
demo功能是隊(duì)列,整個(gè)demo的大致頁(yè)面如下。左邊是存儲(chǔ)到Redis中的數(shù)據(jù),右邊是從Redis中彈出的數(shù)據(jù)。
首先定義一個(gè)存儲(chǔ)list的key
private static final String LIST_KEY = "list:1";
隊(duì)列的key就用list:1
redis操作對(duì)象
private RedisTemplate redisTemplate;//string 命令操作對(duì)象private ValueOperations valueOperations;//list 命令操作對(duì)象private ListOperations listOperations;
list在Redis中的結(jié)構(gòu)可以看下圖(圖片來源于Redis in Action)。
命令 | 用例 | 描述 |
---|---|---|
LPUSH | LPUSH key value [value ...] | 將所有指定的值插入到存于 key 的列表的頭部。 如果 key 不存在,那么在進(jìn)行 push 操作前會(huì)創(chuàng)建一個(gè)空列表。 |
LPUSHX | LPUSHX key value | 只有當(dāng) key 已經(jīng)存在并且存著一個(gè) list 的時(shí)候,在這個(gè) key 下面的 list 的頭部插入 value。 |
接下來看看demo中頭部插入的功能,點(diǎn)擊下圖中頭部插入按鈕,然后在彈出框中填入數(shù)字0,點(diǎn)擊提交后整個(gè)頭部插入流程結(jié)束??梢钥吹阶筮叺年?duì)列數(shù)據(jù)出現(xiàn)了一條{"data":"0"} 數(shù)據(jù),在數(shù)據(jù){"data":"1"} 上面。
來看看后臺(tái)的方法
@RequestMapping(value = "/leftPop",method = RequestMethod.GET)public Object leftPop(){ return listOperations.leftPop(LIST_KEY); }
如果需要在Redis中操作,可以敲下面的命令
lpush list:1 "{\"data\":\"0\"}"
命令 | 用例 | 描述 |
---|---|---|
RPUSH | RPUSH key value [value ...] | 向存于 key 的列表的尾部插入所有指定的值。如果 key 不存在,那么會(huì)創(chuàng)建一個(gè)空的列表然后再進(jìn)行 push 操作。 |
RPUSHX | RPUSHX key value | 將值 value 插入到列表 key 的表尾, 當(dāng)且僅當(dāng) key 存在并且是一個(gè)列表。 |
接下來看看demo中尾部插入的功能,點(diǎn)擊下圖中尾部插入按鈕,然后在彈出框中填入數(shù)字11,點(diǎn)擊提交后整個(gè)新增流程結(jié)束??梢钥吹阶筮叺年?duì)列數(shù)據(jù)出現(xiàn)了一條{"data":"11"} 數(shù)據(jù),在數(shù)據(jù){"data":"10"}下面。
來看看后臺(tái)的方法
@RequestMapping(value = "/rightPop",method = RequestMethod.GET)public Object rightPop(){ return listOperations.rightPop(LIST_KEY); }
如果需要在Redis中操作,可以敲下面的命令
rpush list:1 "{\"data\":\"11\"}"
同樣先看看相關(guān)的獲取值命令
命令 | 用例 | 描述 |
---|---|---|
LRANGE | LRANGE key start stop | 返回存儲(chǔ)在 key 的列表里指定范圍內(nèi)的元素。 |
LINDEX | LINDEX key index | 返回列表里的元素的索引 index 存儲(chǔ)在 key 里面。 |
LLEN | LLEN key | 返回存儲(chǔ)在 key 里的list的長(zhǎng)度。 |
后臺(tái)查詢方法,將新增的內(nèi)容查詢出來
@RequestMapping(value = "/getList",method = RequestMethod.GET)public List getList(){ List list = listOperations.range(LIST_KEY, 0, -1); //可以用size獲取成員長(zhǎng)度 //listOperations.size(LIST_KEY); return list; }
命令 | 用例 | 描述 |
---|---|---|
LPOP | LPOP key | 移除并且返回 key 對(duì)應(yīng)的 list 的第一個(gè)元素。 |
BLPOP | BLPOP key [key ...] timeout | 它是命令 LPOP 的阻塞版本,這是因?yàn)楫?dāng)給定列表內(nèi)沒有任何元素可供彈出的時(shí)候, 連接將被 BLPOP 命令阻塞。 |
接下來看看頭部彈出的功能,點(diǎn)擊下圖中頭部彈出按鈕,可以看到左邊的隊(duì)列頂部數(shù)據(jù)減少了,在右邊彈出的數(shù)據(jù)出現(xiàn)了左邊隊(duì)列數(shù)據(jù)消失的數(shù)據(jù)。
來看看后臺(tái)的方法
@RequestMapping(value = "/leftPop",method = RequestMethod.GET)public Object leftPop(){ return listOperations.leftPop(LIST_KEY); }
如果需要在Redis中操作,可以敲下面的命令
lpop list:1
命令 | 用例 | 描述 |
---|---|---|
RPOP | RPOP key | 移除并返回存于 key 的 list 的最后一個(gè)元素。 |
BRPOP | BRPOP key [key ...] timeout | 它是 RPOP 的阻塞版本,因?yàn)檫@個(gè)命令會(huì)在給定list無法彈出任何元素的時(shí)候阻塞連接。 |
接下來看看尾部彈出的功能,點(diǎn)擊下圖中尾部彈出按鈕,可以看到左邊的隊(duì)列尾部數(shù)據(jù)減少了,在右邊彈出的數(shù)據(jù)出現(xiàn)了左邊隊(duì)列數(shù)據(jù)消失的數(shù)據(jù)。
來看看后臺(tái)的方法
@RequestMapping(value = "/rightPop",method = RequestMethod.GET)public Object rightPop(){ return listOperations.rightPop(LIST_KEY); }
如果需要在Redis中操作,可以敲下面的命令
rpop list:1
命令 | 用例 | 描述 |
|
---|---|---|---|
LINSERT | LINSERT key BEFORE\ | AFTER pivot value | 把 value 插入存于 key 的列表中在基準(zhǔn)值 pivot 的前面或后面。 |
LREM | LREM key count value | 從存于 key 的列表里移除前 count 次出現(xiàn)的值為 value 的元素。 | |
LSET | LSET key index value | 設(shè)置 index 位置的list元素的值為 value。 | |
LTRIM | LTRIM key start stop | 修剪(trim)一個(gè)已存在的 list,這樣 list 就會(huì)只包含指定范圍的指定元素。 | |
RPOPLPUSH | RPOPLPUSH source destination | 原子性地返回并移除存儲(chǔ)在 source 的列表的最后一個(gè)元素(列表尾部元素), 并把該元素放入存儲(chǔ)在 destination 的列表的第一個(gè)元素位置(列表頭部)。 | |
BRPOPLPUSH | BRPOPLPUSH source destination timeout |
BRPOPLPUSH
是
RPOPLPUSH
的阻塞版本。
|
這兩個(gè)命令作用其實(shí)是相同的,只不過BRPOPLPUSH是阻塞的,當(dāng)沒有數(shù)據(jù)時(shí),會(huì)一直阻塞,直到有數(shù)據(jù)。
在Redis官方文檔中,用RPOPLPUSH命令舉了兩個(gè)例子,一個(gè)是Reliable queue(安全的隊(duì)列 ),另一個(gè)是Circular list(循環(huán)列表)。
Redis通常都被用做一個(gè)處理各種后臺(tái)工作或消息任務(wù)的消息服務(wù)器。 一個(gè)簡(jiǎn)單的隊(duì)列模式就是:生產(chǎn)者把消息放入一個(gè)列表中,等待消息的消費(fèi)者用 RPOP 命令(用輪詢方式), 或者用 BRPOP 命令(如果客戶端使用阻塞操作會(huì)更好)來得到這個(gè)消息。
然而,因?yàn)橄⒂锌赡軙?huì)丟失,所以這種隊(duì)列并是不安全的。例如,當(dāng)接收到消息后,出現(xiàn)了網(wǎng)絡(luò)問題或者消費(fèi)者端崩潰了, 那么這個(gè)消息就丟失了。
RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH ) 提供了一種方法來避免這個(gè)問題:消費(fèi)者端取到消息的同時(shí)把該消息放入一個(gè)正在處理中的列表。 當(dāng)消息被處理了之后,該命令會(huì)使用 LREM 命令來移除正在處理中列表中的對(duì)應(yīng)消息。
另外,可以添加一個(gè)客戶端來監(jiān)控這個(gè)正在處理中列表,如果有某些消息已經(jīng)在這個(gè)列表中存在很長(zhǎng)時(shí)間了(即超過一定的處理時(shí)限), 那么這個(gè)客戶端會(huì)把這些超時(shí)消息重新加入到隊(duì)列中。
翻譯來自 http://www.redis.cn/commands/rpoplpush.html
RPOPLPUSH 命令的 source 和 destination 是相同的話, 那么客戶端在訪問一個(gè)擁有n個(gè)元素的列表時(shí),可以在 O(N) 時(shí)間里一個(gè)接一個(gè)獲取列表元素, 而不用像 LRANGE 那樣需要把整個(gè)列表從服務(wù)器端傳送到客戶端。
上面這種模式即使在以下兩種情況下照樣能很好地工作: 有多個(gè)客戶端同時(shí)對(duì)同一個(gè)列表進(jìn)行旋轉(zhuǎn)(rotating):它們會(huì)取得不同的元素,直到列表里所有元素都被訪問過,又從頭開始這個(gè)操作。 有其他客戶端在往列表末端加入新的元素。
這個(gè)模式讓我們可以很容易地實(shí)現(xiàn)這樣一個(gè)系統(tǒng):有 N 個(gè)客戶端,需要連續(xù)不斷地對(duì)一批元素進(jìn)行處理,而且處理的過程必須盡可能地快。 一個(gè)典型的例子就是服務(wù)器上的監(jiān)控程序:它們需要在盡可能短的時(shí)間內(nèi),并行地檢查一批網(wǎng)站,確保它們的可訪問性。
值得注意的是,使用這個(gè)模式的客戶端是易于擴(kuò)展(scalable)且安全的(reliable),因?yàn)榧词箍蛻舳税呀邮盏降南G失了, 這個(gè)消息依然存在于隊(duì)列中,等下次迭代到它的時(shí)候,由其他客戶端進(jìn)行處理。
翻譯來自 http://www.redis.cn/commands/rpoplpush.html
約瑟夫問題 (有時(shí)也稱為 約瑟夫斯置換 ),是一個(gè)出現(xiàn)在 計(jì)算機(jī)科學(xué) 和 數(shù)學(xué) 中的問題。在計(jì)算機(jī) 編程 的算法中,類似問題又稱為 約瑟夫環(huán) 。
人們站在一個(gè)等待被處決的圈子里。 計(jì)數(shù)從圓圈中的指定點(diǎn)開始,并沿指定方向圍繞圓圈進(jìn)行。 在跳過指定數(shù)量的人之后,執(zhí)行下一個(gè)人。 對(duì)剩下的人重復(fù)該過程,從下一個(gè)人開始,朝同一方向跳過相同數(shù)量的人,直到只剩下一個(gè)人,并被釋放。
問題即,給定人數(shù)、起點(diǎn)、方向和要跳過的數(shù)字,選擇初始圓圈中的位置以避免被處決。
來自維基百科 https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98
定義一個(gè)list key為josephus,利用
RPOPLPUSH josephus josephus
命令來構(gòu)造循環(huán)鏈表,每當(dāng)數(shù)到3時(shí),使用rpop
rpop josephus
命令彈出
public class JosephusProblem extends RedisBaseConnection { @Test public void test() { //構(gòu)造數(shù)據(jù) for (int i = 1; i <= 41; i++) { listOperations.leftPush("josephus", String.valueOf(i)); } int index = 1; while (listOperations.size("josephus") > 0) { //當(dāng)數(shù)到3時(shí),彈出 if (index == 3) { System.out.println(listOperations.range("josephus", 0, -1)); System.out.println("當(dāng)前被殺的人是:" + listOperations.rightPop("josephus")); index = 0; } else { listOperations.rightPopAndLeftPush("josephus", "josephus"); } index++; } } }
整個(gè)代碼步驟如下
先是模擬有41個(gè)人(向redis中key為josephus的list添加41個(gè)數(shù)據(jù))
定義索引index
循環(huán)判斷key為josephus的數(shù)據(jù)長(zhǎng)度是否大于0
當(dāng)索引index為3時(shí),調(diào)用Redis的rpop命令彈出對(duì)應(yīng)的數(shù)據(jù)。索引index不為3時(shí),調(diào)用RPOPLPUSH命令,將對(duì)應(yīng)的數(shù)據(jù)放到隊(duì)列頭部
索引index加1
運(yùn)行結(jié)果有點(diǎn)長(zhǎng),這里只截圖最后一部分的結(jié)果,如下
約瑟夫問題代碼請(qǐng)點(diǎn)擊 JosephusProblem.java
建議學(xué)習(xí)的人最好每個(gè)命令都去敲下,加深印象。下面詩(shī)句送給你們。
紙上得來終覺淺,絕知此事要躬行。————出自《冬夜讀書示子聿》
當(dāng)前標(biāo)題:redis系列:通過隊(duì)列案例學(xué)習(xí)list命令-創(chuàng)新互聯(lián)
新聞來源:http://jinyejixie.com/article8/dpsgip.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、搜索引擎優(yōu)化、電子商務(wù)、網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站收錄、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容