乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【Redis02】Redis基礎(chǔ):List相關(guān)操作

       硬核項目經(jīng)理 2023-03-09 發(fā)布于湖南

      Redis基礎(chǔ)學習:List相關(guān)操作

      在 Redis 中,List 也是非常常用的一個數(shù)據(jù)類型,它可以看做是我們 PHP 中的數(shù)字下標類型的數(shù)組,注意,是數(shù)字下標的那種最典型的數(shù)組格式。重要的是,它可以方便地幫助我們實現(xiàn)隊列或者棧的功能,非常強大。同樣的,我們還是先來學習一下它的一些基本操作命令。

      添加元素

      添加元素就是兩個命令,RPUSH 和 LPUSH ,分別從 List 的右邊或者左邊添加數(shù)據(jù)。

      127.0.0.1:6379> lpush a 1 2 3
      (integer) 3
      127.0.0.1:6379> rpush a -3 -2 -1
      (integer) 6
      127.0.0.1:6379> llen a
      (integer) 6
      127.0.0.1:6379> lrange a 0 5
      1) "3"
      2) "2"
      3) "1"
      4) "-3"
      5) "-2"
      6) "-1"

      上面的例子中,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ù)的方式。

      127.0.0.1:6379> lpushx b 1 2 3
      (integer) 0
      127.0.0.1:6379> rpushx b -1 -2 -3
      (integer) 0

      RPUSHX 和 LPUSHX 的意思是如果指定的 key 不存在,則無法添加數(shù)據(jù)。

      修改指定下標元素

      能設(shè)置,當然也能修改啦,修改使用的是 LSET 命令,它是根據(jù)指定的下標進行數(shù)據(jù)修改的。

      127.0.0.1:6379> lset a 3 -33
      OK
      127.0.0.1:6379> lrange a 0 -1
      1) "3"
      2) "2"
      3) "1"
      4) "-33"
      5) "-2"
      6) "-1"

      127.0.0.1:6379> lset b 0 1
      (error) ERR no such key

      127.0.0.1:6379> lset a 22 1
      (error) ERR index out of range

      如果指定的下標不存在或者是指定的 key 不存在,就無法修改,并且會分別報出不同的錯誤。

      根據(jù)指定元素值插入

      插入數(shù)據(jù)是根據(jù)某個值的內(nèi)容進行插入,注意,它不是根據(jù)下標哦。

      127.0.0.1:6379> linsert a before -33 -22
      (integer) 7
      127.0.0.1:6379> linsert a after -33 -11
      (integer) 8
      127.0.0.1:6379> lrange a 0 -1
      1) "3"
      2) "2"
      3) "1"
      4) "-22"
      5) "-33"
      6) "-11"
      7) "-2"
      8) "-1"

      從上面的例子可以看出,LINSERT 命令有一個參數(shù)可以設(shè)置為 BEFORE 或者 AFTER ,分別代表根據(jù)指定值,從它的前面或者后面插入數(shù)據(jù)。

      127.0.0.1:6379> linsert a after -33 -33
      (integer) 9
      127.0.0.1:6379> lrange a 0 -1
      1) "3"
      2) "2"
      3) "1"
      4) "-22"
      5) "-33"
      6) "-33"
      7) "-11"
      8) "-2"
      9) "-1"
      127.0.0.1:6379> linsert a after -33 -111
      (integer) 10
      127.0.0.1:6379> linsert a before -33 -222
      (integer) 11
      127.0.0.1:6379> lrange a 0 -1
       1) "3"
       2) "2"
       3) "1"
       4) "-22"
       5) "-222"
       6) "-33"
       7) "-111"
       8) "-33"
       9) "-11"
      10) "-2"
      11) "-1"

      插入成功后,會返回 List 的長度,如果列表 key 不存在,則不會有任何操作發(fā)生,如果指定的插入數(shù)據(jù)不存在,則會返回 -1 ,如果 key 存在,但它不是一個 List 類型的話,那么會報錯。

      獲取元素

      添加、修改、插入元素的操作非常簡單,但其實我們最常用的就是添加那兩個,也就是 LPUSH 和 RPUSH 。同樣的,在獲取元素中,我們最常用的也僅是那么幾個命令,不過既然是基礎(chǔ)的學習,我們還是一個一個的都過一遍。

      獲取指定下標的元素

      通過 LINDEX 命令,就可以獲取到指定下標的元素數(shù)據(jù)。

      127.0.0.1:6379> lindex a 7
      "-33"
      127.0.0.1:6379> lindex b 7
      (nil)
      127.0.0.1:6379> lindex a 22
      (nil)
      127.0.0.1:6379> lindex a -6
      "-33"

      和之前說過的一樣,這里的下標也是可以使用負數(shù)反向獲取的。

      根據(jù)值獲取下標

      除了通過下標獲取元素之外,還可以通過 LPOS 獲取到指定元素的下標。

      127.0.0.1:6379> lpos a -33
      (integer) 5

      很顯然,在默認情況下,它返回的是第一個元素的下標,因為在上面的操作中,我們已經(jīng)有多個 -33 這條數(shù)據(jù)了。那么怎么獲取到其它的 -33 的下標呢?

      127.0.0.1:6379> rpush a -33 baz -33 bar open
      (integer) 16
      127.0.0.1:6379> lrange a 0 -1
       1) "3"
       2) "2"
       3) "1"
       4) "-22"
       5) "-222"
       6) "-33"
       7) "-111"
       8) "-33"
       9) "-11"
      10) "-2"
      11) "-1"
      12) "-33"
      13) "baz"
      14) "-33"
      15) "bar"
      16) "open"

      首先,我們多添加一些數(shù)據(jù),現(xiàn)在整個 List 中有四個 -33 元素。

      127.0.0.1:6379> lpos a -33 rank 2
      (integer) 7
      127.0.0.1:6379> lpos a -33 rank -2
      (integer) 11

      RANK 參數(shù),表示我們現(xiàn)在要獲取第幾個指定的值的下標。例子中的正數(shù) 2 就是正數(shù)第二個 -33 的下標,也就是 7 ,-2 表示倒數(shù)第二個 -33 的下標值,也就是下標為 11 的數(shù)據(jù)。除了指定顯示第幾個之外,我們還可以指定返回多少個,使用 COUNT 參數(shù)。

      127.0.0.1:6379> lpos a -33 count 3
      1) (integer) 5
      2) (integer) 7
      3) (integer) 11
      127.0.0.1:6379> lpos a -33 count 4
      1) (integer) 5
      2) (integer) 7
      3) (integer) 11
      4) (integer) 13
      127.0.0.1:6379> lpos a -33 count 0
      1) (integer) 5
      2) (integer) 7
      3) (integer) 11
      4) (integer) 13

      默認情況下,COUNT 參數(shù)就是 1,也就是返回 1 條數(shù)據(jù)。如果我們指定了,就返回符合指定數(shù)據(jù)的查找數(shù)據(jù)。如果設(shè)置為 0 的話,就表示返回全部符合的數(shù)據(jù)下標。當然,RANK 和 COUNT 也可以組合使用。

      127.0.0.1:6379> lpos a -33 count 0 rank 2
      1) (integer) 7
      2) (integer) 11
      3) (integer) 13

      這個例子中,返回的是除了第一個之外的全部 -33 的下標。

      127.0.0.1:6379> lpos a -333
      (nil)
      127.0.0.1:6379> lpos a -333 count 1
      (empty array)

      如果查找的數(shù)據(jù)不存在,會返回 nil ,不過有個特殊情況,那就是如果使用了 COUNT 返回的話,它本身就會將結(jié)果變成數(shù)組返回,所以如果在這種情況如果沒有找到數(shù)據(jù),就會返回一個空數(shù)組。

      彈出

      彈出操作是實現(xiàn)?;蛘哧犃械闹匾睿彩谴蠹視?jīng)常使用的兩個命令,分別是 RPOP 和 LPOP ,很明顯,就是分別從右、左彈出數(shù)據(jù)。彈出的意思就是返回這條數(shù)據(jù)并且在 List 中刪除它。

      127.0.0.1:6379> lpop a
      "3"
      127.0.0.1:6379> lpop a 2
      1) "2"
      2) "1"
      127.0.0.1:6379> rpop a
      "open"
      127.0.0.1:6379> rpop a 3
      1) "bar"
      2) "-33"
      3) "baz"
      127.0.0.1:6379> llen a
      (integer) 9

      127.0.0.1:6379> rpop b
      (nil)

      如果指定 key 不存在,那么這兩個命令返回的就是 nil 空。

      有了這兩個命令,實現(xiàn)隊列和棧就非常簡單了吧。隊列的話,如果是 RPUSH ,那就 LPOP ,反過來也行。棧就更簡單了 RPUSH 配合 RPOP 就好啦!

      數(shù)據(jù)移動

      數(shù)據(jù)移動在 6.2 之前的版本是使用 RPOPPUSH ,但在 6.2 之后這個命令就被標為過時了,并且新出了一個 LMOVE 命令。我們就以最新的來進行學習吧。

      LMOVE source destination LEFT|RIGHT LEFT|RIGHT

      LMOVE 的命令調(diào)用方法看著有點蒙啊,其實很好理解。source 表示從哪里移動,destination表示移動到的目標,也就是移動到哪里去。后面兩個參數(shù)分別代表是LPOP/RPOP source 和 LPUSH/RPUSH destination 。

      127.0.0.1:6379> lmove a a1 left left
      "-22"
      127.0.0.1:6379> lmove a a1 left left
      "-222"
      127.0.0.1:6379> lrange a1 0 -1
      1) "-222"
      2) "-22"
      127.0.0.1:6379> lmove a a1 left right
      "-33"
      127.0.0.1:6379> lrange a1 0 -1
      1) "-222"
      2) "-22"
      3) "-33"
      127.0.0.1:6379> lmove a a1 right left
      "-33"
      127.0.0.1:6379> lrange a1 0 -1
      1) "-33"
      2) "-222"
      3) "-22"
      4) "-33"

      我們先從之前的 a 中 LPOP 兩條數(shù)據(jù) LPUSH 到了 a1 中,然后再從 a 中 LPOP 一條數(shù)據(jù) RPUSH 到 a1 中,最后,再從 a 中 RPOP 一條數(shù)據(jù) LPUSH 到了 a1 中。

      原子阻塞彈出

      這是啥意思?我們使用 BLPOP 或者 BRPOP ,當隊列空的時候,它會阻塞到這里,直到獲取到下一條數(shù)據(jù)。

      127.0.0.1:6379> blpop a a1 0
      1) "a"
      2) "-111"
      ...........
      127.0.0.1:6379> blpop a a1 0
      1) "a1"
      2) "-33"
      127.0.0.1:6379> blpop a a1 0

      我們先彈出所有的數(shù)據(jù),注意,這個 BLPOP 是可以同時彈出多個隊列的,我們在這個例子中,同時把 a 和 a1 的都彈完,當彈出的時候,返回的是一個列表,第一個值是列表的名稱,第二個是彈出的值。兩個隊列中都沒有數(shù)據(jù)后,BLPOP 就阻塞在這里了。最后一個參數(shù)的 0 表示的是超時時間,如果過了超時時間還沒有新的元素插入到這兩個 List 中,就會結(jié)束阻塞,而如果設(shè)置為 0 的話,就會一直等待。

      127.0.0.1:6379> lpush a1 1
      (integer) 1

      接著另開一個 redis-cli 客戶端,然后為 a1 添加一條數(shù)據(jù)。

      127.0.0.1:6379> blpop a a1 0
      1) "a1"
      2) "1"
      (16.57s)

      之前的那個客戶端中阻塞的隊列馬上響應(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 類似的,所以大家直接看下代碼就好了。

      127.0.0.1:6379> blmove a a1 left left 0

      首先我們讓 a 的數(shù)據(jù)全部彈出,現(xiàn)在 BLMOVE 也是在阻塞狀態(tài)。

      127.0.0.1:6379> lpush a1 1
      (integer) 1
      127.0.0.1:6379> lpush a 1
      (integer) 1

      接著還是通過另一個客戶端插入數(shù)據(jù),注意,我們給 a1 插入數(shù)據(jù)的時候不會有動靜,因為我們需要給 source 插入數(shù)據(jù)才會發(fā)生數(shù)據(jù)移動。

      127.0.0.1:6379> blmove a a1 left left 0
      "1"
      (11.85s)
      127.0.0.1:6379> lrange a1 0 -1
      1) "1"
      2) "1"

      好了,a 新插入的數(shù)據(jù)馬上被移動到了 a1 中。

      刪除元素

      其實上面 POP 相關(guān)的操作也是一種刪除操作,但它們都是定死的只能從某一個方向去把數(shù)據(jù)彈出來。真正的刪除肯定是我們?nèi)ルS便刪除指定的數(shù)據(jù)嘛,先來看看 LREM 這個命令。

      LREM 是根據(jù)提供的值,去刪除元素。注意,不是下標,不是下標,不是下標。

      127.0.0.1:6379> lpush a 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3
      (integer) 17
      127.0.0.1:6379> lrem a 4 1
      (integer) 3
      127.0.0.1:6379> lrem a 2 2
      (integer) 2
      127.0.0.1:6379> lrange a 0 -1
       1) "3"
       2) "7"
       3) "6"
       4) "5"
       5) "4"
       6) "3"
       7) "7"
       8) "6"
       9) "5"
      10) "4"
      11) "3"
      12) "2"

      第一次,我們刪除了 4 這個元素,后面的 1 表示只刪除 1 個 4 。第二次刪除了 2 個 2 。這個例子不太好,因為我的數(shù)據(jù)也是數(shù)字,但是,大家要是能一眼看明白這段代碼的意思,就能很清楚地明白 LREM 是刪除值而不是下標的意思了。

      只保留指定區(qū)間元素

      除了刪除指定的值之外,我們還可以按范圍刪除,或者說是按范圍保留。

      127.0.0.1:6379> ltrim a 2 5
      OK
      127.0.0.1:6379> lrange a 0 -1
      1) "6"
      2) "5"
      3) "4"
      4) "3"

      LTRIM key 2 5 的意思就是只保留下標 2 到 5 的數(shù)據(jù),或者反過來說是把 0、1 和 5 之后的數(shù)據(jù)都刪除了。

      刪除指定下標元素

      Redis 中沒有提供按指定下標刪除 List 數(shù)據(jù)的命令,那要實現(xiàn)刪除指定下標的元素要怎么弄呢?

      127.0.0.1:6379> lset a 1 -1
      OK
      127.0.0.1:6379> lrem a 1 -1
      (integer) 1
      127.0.0.1:6379> lrange a 0 -1
      1) "6"
      2) "4"
      3) "3"

      使用 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),后面我們也會學習到。

        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多