Redis基礎(chǔ)學習:List相關(guān)操作在 Redis 中,List 也是非常常用的一個數(shù)據(jù)類型,它可以看做是我們 PHP 中的數(shù)字下標類型的數(shù)組,注意,是數(shù)字下標的那種最典型的數(shù)組格式。重要的是,它可以方便地幫助我們實現(xiàn)隊列或者棧的功能,非常強大。同樣的,我們還是先來學習一下它的一些基本操作命令。 添加元素添加元素就是兩個命令,RPUSH 和 LPUSH ,分別從 List 的右邊或者左邊添加數(shù)據(jù)。
上面的例子中,LPUSH 從左邊添加,1最先被添加進去,然后是 2 ,因此,返回的順序是 3 2 1 這樣的。同理,RPUSH 的時候,我們是從右邊添加,-3 -2 -1 從右邊依次進入的順序就是我們寫的 -3 -2 -1 這個順序。這兩個命令操作成功后都會返回 List 的長度,如果指定的 key 不存在的話,就創(chuàng)建新的 List 。 LLEN 可以獲取 List 的長度。LRANGE 返回 List 中的數(shù)據(jù),它有兩個參數(shù),分別是開始位置和結(jié)束位置,其實我們可以使用 LRANGE a 0 -1 來獲取 List 中的全部元素。注意,-1 表示的反向取數(shù)據(jù),你可以把這種下標看成是一種 環(huán)形 取數(shù)據(jù)的方式。
RPUSHX 和 LPUSHX 的意思是如果指定的 key 不存在,則無法添加數(shù)據(jù)。 修改指定下標元素能設(shè)置,當然也能修改啦,修改使用的是 LSET 命令,它是根據(jù)指定的下標進行數(shù)據(jù)修改的。
如果指定的下標不存在或者是指定的 key 不存在,就無法修改,并且會分別報出不同的錯誤。 根據(jù)指定元素值插入插入數(shù)據(jù)是根據(jù)某個值的內(nèi)容進行插入,注意,它不是根據(jù)下標哦。
從上面的例子可以看出,LINSERT 命令有一個參數(shù)可以設(shè)置為 BEFORE 或者 AFTER ,分別代表根據(jù)指定值,從它的前面或者后面插入數(shù)據(jù)。
插入成功后,會返回 List 的長度,如果列表 key 不存在,則不會有任何操作發(fā)生,如果指定的插入數(shù)據(jù)不存在,則會返回 -1 ,如果 key 存在,但它不是一個 List 類型的話,那么會報錯。 獲取元素添加、修改、插入元素的操作非常簡單,但其實我們最常用的就是添加那兩個,也就是 LPUSH 和 RPUSH 。同樣的,在獲取元素中,我們最常用的也僅是那么幾個命令,不過既然是基礎(chǔ)的學習,我們還是一個一個的都過一遍。 獲取指定下標的元素通過 LINDEX 命令,就可以獲取到指定下標的元素數(shù)據(jù)。
和之前說過的一樣,這里的下標也是可以使用負數(shù)反向獲取的。 根據(jù)值獲取下標除了通過下標獲取元素之外,還可以通過 LPOS 獲取到指定元素的下標。
很顯然,在默認情況下,它返回的是第一個元素的下標,因為在上面的操作中,我們已經(jīng)有多個 -33 這條數(shù)據(jù)了。那么怎么獲取到其它的 -33 的下標呢?
首先,我們多添加一些數(shù)據(jù),現(xiàn)在整個 List 中有四個 -33 元素。
RANK 參數(shù),表示我們現(xiàn)在要獲取第幾個指定的值的下標。例子中的正數(shù) 2 就是正數(shù)第二個 -33 的下標,也就是 7 ,-2 表示倒數(shù)第二個 -33 的下標值,也就是下標為 11 的數(shù)據(jù)。除了指定顯示第幾個之外,我們還可以指定返回多少個,使用 COUNT 參數(shù)。
默認情況下,COUNT 參數(shù)就是 1,也就是返回 1 條數(shù)據(jù)。如果我們指定了,就返回符合指定數(shù)據(jù)的查找數(shù)據(jù)。如果設(shè)置為 0 的話,就表示返回全部符合的數(shù)據(jù)下標。當然,RANK 和 COUNT 也可以組合使用。
這個例子中,返回的是除了第一個之外的全部 -33 的下標。
如果查找的數(shù)據(jù)不存在,會返回 nil ,不過有個特殊情況,那就是如果使用了 COUNT 返回的話,它本身就會將結(jié)果變成數(shù)組返回,所以如果在這種情況如果沒有找到數(shù)據(jù),就會返回一個空數(shù)組。 彈出彈出操作是實現(xiàn)?;蛘哧犃械闹匾睿彩谴蠹視?jīng)常使用的兩個命令,分別是 RPOP 和 LPOP ,很明顯,就是分別從右、左彈出數(shù)據(jù)。彈出的意思就是返回這條數(shù)據(jù)并且在 List 中刪除它。
如果指定 key 不存在,那么這兩個命令返回的就是 nil 空。 有了這兩個命令,實現(xiàn)隊列和棧就非常簡單了吧。隊列的話,如果是 RPUSH ,那就 LPOP ,反過來也行。棧就更簡單了 RPUSH 配合 RPOP 就好啦! 數(shù)據(jù)移動數(shù)據(jù)移動在 6.2 之前的版本是使用 RPOPPUSH ,但在 6.2 之后這個命令就被標為過時了,并且新出了一個 LMOVE 命令。我們就以最新的來進行學習吧。
LMOVE 的命令調(diào)用方法看著有點蒙啊,其實很好理解。source 表示從哪里移動,destination表示移動到的目標,也就是移動到哪里去。后面兩個參數(shù)分別代表是LPOP/RPOP source 和 LPUSH/RPUSH destination 。
我們先從之前的 a 中 LPOP 兩條數(shù)據(jù) LPUSH 到了 a1 中,然后再從 a 中 LPOP 一條數(shù)據(jù) RPUSH 到 a1 中,最后,再從 a 中 RPOP 一條數(shù)據(jù) LPUSH 到了 a1 中。 原子阻塞彈出這是啥意思?我們使用 BLPOP 或者 BRPOP ,當隊列空的時候,它會阻塞到這里,直到獲取到下一條數(shù)據(jù)。
我們先彈出所有的數(shù)據(jù),注意,這個 BLPOP 是可以同時彈出多個隊列的,我們在這個例子中,同時把 a 和 a1 的都彈完,當彈出的時候,返回的是一個列表,第一個值是列表的名稱,第二個是彈出的值。兩個隊列中都沒有數(shù)據(jù)后,BLPOP 就阻塞在這里了。最后一個參數(shù)的 0 表示的是超時時間,如果過了超時時間還沒有新的元素插入到這兩個 List 中,就會結(jié)束阻塞,而如果設(shè)置為 0 的話,就會一直等待。
接著另開一個 redis-cli 客戶端,然后為 a1 添加一條數(shù)據(jù)。
之前的那個客戶端中阻塞的隊列馬上響應(yīng)并彈出了一條數(shù)據(jù),并且下面還標明了本次等待的時間。 這個東西有什么用呢?在某些場景中,比如我們后臺消費隊列的場景一般就會是一個進程不停地執(zhí)行消費,通常我們可能會寫一個死循環(huán),然后每次循環(huán)的時候查找隊列中是否有內(nèi)容,寫個 LPOP 如果返回空,就 sleep() 一會,如果下次還沒查到,就再 sleep() 一會?,F(xiàn)在,我們可以替換成使用 BLPOP ,其實就是省去了 sleep() 的過程,并且也可以減少反復遠程查詢的次數(shù)。 有 POP 操作,對應(yīng)的也有阻塞的 BLMOVE 操作,這個命令也是 6.2 之后才有的,替換之前的 BRPOPPUSH 命令。概念也是和 LMOVE 類似的,所以大家直接看下代碼就好了。
首先我們讓 a 的數(shù)據(jù)全部彈出,現(xiàn)在 BLMOVE 也是在阻塞狀態(tài)。
接著還是通過另一個客戶端插入數(shù)據(jù),注意,我們給 a1 插入數(shù)據(jù)的時候不會有動靜,因為我們需要給 source 插入數(shù)據(jù)才會發(fā)生數(shù)據(jù)移動。
好了,a 新插入的數(shù)據(jù)馬上被移動到了 a1 中。 刪除元素其實上面 POP 相關(guān)的操作也是一種刪除操作,但它們都是定死的只能從某一個方向去把數(shù)據(jù)彈出來。真正的刪除肯定是我們?nèi)ルS便刪除指定的數(shù)據(jù)嘛,先來看看 LREM 這個命令。 LREM 是根據(jù)提供的值,去刪除元素。注意,不是下標,不是下標,不是下標。
第一次,我們刪除了 4 這個元素,后面的 1 表示只刪除 1 個 4 。第二次刪除了 2 個 2 。這個例子不太好,因為我的數(shù)據(jù)也是數(shù)字,但是,大家要是能一眼看明白這段代碼的意思,就能很清楚地明白 LREM 是刪除值而不是下標的意思了。 只保留指定區(qū)間元素除了刪除指定的值之外,我們還可以按范圍刪除,或者說是按范圍保留。
LTRIM key 2 5 的意思就是只保留下標 2 到 5 的數(shù)據(jù),或者反過來說是把 0、1 和 5 之后的數(shù)據(jù)都刪除了。 刪除指定下標元素Redis 中沒有提供按指定下標刪除 List 數(shù)據(jù)的命令,那要實現(xiàn)刪除指定下標的元素要怎么弄呢?
使用 LSET 和 LREM 配合起來,先將要刪除的下標位置的元素改成一個固定的值,比如我這里用的 -1 ,或者你也可以用 del 、invalid 之類的字符串。然后使用 LREM 去批量刪除它們就好了。 總結(jié)奇怪的小知識又增加了吧?說實話,之前我還真不知道 LMOVE 和 BLPOP 這一類的東西,既然知道了,那么下回做隊列的時候咱也可以試試了。List 相關(guān)的操作命令就是這些,其實也不難,你可以把它當成是一個可以方便地實現(xiàn)隊列和棧的數(shù)組,其實之前我也一直就只是把它當普通隊列來用的,更復雜的優(yōu)先和延時隊列在 Redis 中還有別的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn),后面我們也會學習到。 |
|
來自: 硬核項目經(jīng)理 > 《待分類》