redis之list---RPOPLPUSH

來源:互聯網
上載者:User

1.RPOPLPUSH

LPOPLPUSH source destination

命令RPOPLPUSH在一個原子時間內,執行以下兩個動作:

①將列表source中最後一個元素(尾元素)彈出,並返回給用戶端。

②將source彈出的元素插入到列表destination,作為destination列表的頭元素。

舉個例子,你有兩個列表source和destination,source列表有元素a,b,c,destination列表有元素x,y,z,執行RPOPLPUSH source destination之後,source列表包含元素a,b,destination列表包含元素c,x,y,z,並且元素c會被返回給用戶端。

如果source不存在,值nil被返回,並且不執行其他動作。

如果source和destination相同,則列表中的表尾元素被移動到表頭,並返回該元素,可以把這種特殊情況視作為列表的旋轉操作。

傳回值:

被彈出的元素。

命令:

# source 和 destination 不同redis> LRANGE alpha 0 -1         # 查看所有元素1) "a"2) "b"3) "c"4) "d"redis> RPOPLPUSH alpha reciver   # 執行一次 RPOPLPUSH 看看"d"redis> LRANGE alpha 0 -11) "a"2) "b"3) "c"redis> LRANGE reciver 0 -11) "d"redis> RPOPLPUSH alpha reciver   # 再執行一次,證實 RPOP 和 LPUSH 的位置正確"c"redis> LRANGE alpha 0 -11) "a"2) "b"redis> LRANGE reciver 0 -11) "c"2) "d" # source 和 destination 相同redis> LRANGE number 0 -11) "1"2) "2"3) "3"4) "4"redis> RPOPLPUSH number number"4"redis> LRANGE number 0 -1           # 4 被旋轉到了表頭1) "4"2) "1"3) "2"4) "3"redis> RPOPLPUSH number number"3"redis> LRANGE number 0 -1           # 這次是 3 被旋轉到了表頭1) "3"2) "4"3) "1"4) "2"
模式:安全地隊列

Redis的列表經常被用作隊列(queue),用於在不同程式之間有序地交換訊息,一個用戶端通過LPUSH命令將訊息放入到隊列中,而另一個用戶端通過RPOP或者BRPOP命令取出隊列中等待時間最長的訊息。

不幸的是,上面的隊列方法是不安全的,因為在這個過程中,一個用戶端可能在取出一個訊息之後崩潰,而未處理完的訊息也就因此丟失。

使用RPOPLPUSH命令可以解決這個問題,因為它不僅返回一個訊息,同時還將這個訊息添加到另一個備份列表當中,如果一切正常的話,當一個用戶端完成某個訊息的處理之後,可以用LREM命令將這個訊息從備份表刪除。

最後,還可以添加一個用戶端專門用於監視備份表,它自動地將超過一個處理

時限的訊息重新放入隊列中去(負責處理該訊息的用戶端可能已經崩潰),這樣就不會丟失任何訊息了。

模式:迴圈列表

通過使用相同的key作為RPOPLPUSH命令的兩個參數,用戶端可以用一個接一個地擷取列表元素的方式,取得列表的所有元素,而不必像LRANGE命令那樣一下子將所有列表元素都從伺服器傳送到用戶端中(兩種方式的總複雜度都是o(N))。

以上模式甚至在以下的兩個情況下也能正常工作:

①有多個用戶端同時對一個列表進行旋轉,它們擷取不同的元素,知道所有元素都被讀取完,之後又從頭開始。

②有用戶端在向列表尾部(右邊)添加新元素。

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

注意:使用這個模式的用戶端是易於擴充且安全地,因為就算接收到元素的用戶端失敗,元素還是儲存在列表裡面,不會丟失,等到下個迭代來臨的時候,別的用戶端又可以繼續處理這些元素了。

 2.RPUSH

RPUSH key value [value ...]

將一個或多個值value插入到列表key的表尾(最右邊)。

如果有多個value值,那麼各個value值按從左至右的順序依次插入到表尾:比如對一個空列表mylist執行RPUSH mylist a b c,得出的結果清單為a b c,等同於執行命令RPUSH mylist a、 RPUSH mylist b、 RPUSH mylist c。

如果key不存在,一個空列表會被建立並執行RPUSH操作。

當key存在但不是清單類型時,返回一個錯誤。

傳回值:

執行RPUSH操作後,表的長度。

命令:

# 添加單個元素redis> RPUSH languages c(integer) 1# 添加重複元素redis> RPUSH languages c(integer) 2redis> LRANGE languages 0 -1 # 列表允許重複元素1) "c"2) "c"# 添加多個元素redis> RPUSH mylist a b c(integer) 3redis> LRANGE mylist 0 -11) "a"2) "b"3) "c"
3.RPUSHX

RPUSH key value

將值value插入到列表key的表尾,若且唯若key存在並且是一個非空列表。

和RPUSH命令相反,當key不存在時,RPUSH命令什麼也不做。

傳回值:

RPUSHX命令執行之後,表的長度

命令:

# key不存在redis> LLEN greet(integer) 0redis> RPUSHX greet "hello"     # 對不存在的 key 進行 RPUSHX,PUSH 失敗。(integer) 0# key 存在且是一個非空列表redis> RPUSH greet "hi"         # 先用 RPUSH 插入一個元素(integer) 1redis> RPUSHX greet "hello"     # greet 現在是一個清單類型,RPUSHX 操作成功。(integer) 2redis> LRANGE greet 0 -11) "hi"2) "hello"
4.BLPOP

BLPOP key [key ... ] timeout

BLPOP是列表的阻塞式彈出原語。

它是LPOP命令的阻塞版本,當給定列表內沒有任何元素可供彈出的時候,串連將被BLPOP命令阻塞,直到等待逾時或發現可彈出元素為止。

當給定多個key參數時,按參數key的先後順序依次檢查各個列表,彈出第一個非空列表的頭元素。

非阻塞行為

當BLPOP被調用時,如果給定key內至少有一個非空列表,那麼彈出遇到的第一個非空列表額頭元素,並和被彈出元素所屬的列表的名字在一起,組成結果返回給調用者。

當存在多個給定key時,BLPOP按給定key參數排列的先後順序,依次檢查各個列表。

假設現在有job,command和request三個列表,其中job不存在,command和request都持有非空列表。考慮一下命令:

BLPOP job command request 0

BLPOP保證返回的元素來自command,因為它是按“尋找job---->尋找command----->尋找request”這樣的順序,第一個找到的非空列表。

命令:

redis> DEL job command request           # 確保key都被刪除(integer) 0redis> LPUSH command "update system..."  # 為command列表增加一個值(integer) 1redis> LPUSH request "visit page"        # 為request列表增加一個值(integer) 1redis> BLPOP job command request 0       # job 列表為空白,被跳過,緊接著 command 列表的第一個元素被彈出。1) "command"                             # 彈出元素所屬的列表2) "update system..."                    # 彈出元素所屬的值
阻塞行為

如果所有給定key都不存在或包含空列表,那麼BLPOP命令將阻塞串連,直到等待逾時,或者有另外一個用戶端對給定key的任意一個執行LPUSH或RPUSH命令為止。

逾時參數timeout接受一個以秒為單位的數字作為值。逾時參數設為0表示阻塞時間可以無限延長

命令:

redis> EXISTS job                # 確保兩個 key 都不存在(integer) 0redis> EXISTS command(integer) 0redis> BLPOP job command 300     # 因為key一開始不存在,所以操作會被阻塞,直到另一用戶端對 job 或者 command 列表進行 PUSH 操作。1) "job"                         # 這裡被 push 的是 job2) "do my home work"             # 被彈出的值(26.26s)                         # 等待的秒數redis> BLPOP job command 5       # 等待逾時的情況(nil)(5.66s)                          # 等待的秒數


相同的key被多個用戶端同時阻塞

相同的key可以被多個用戶端同時阻塞

不同的用戶端被放進一個隊列中,按【先阻塞先服務】的順序為key執行BLPOP命令。

在MULTI/EXEC事物中的BLPOP

BLPOP可以用於流水線(pipline,批量地發送多個命令並讀入多個回複),但把它用在MULTI/EXEC塊當中沒有意義。因為這要求整個服務被阻塞以保證塊執行時的原子性,該行為阻止了其他用戶端執行LPUSH或RPUSH命令。

因此,一個被包裹在MULTI/EXEC塊內的BLPOP命令,行為表現就得像LPOP一樣,對空列表返回nil,對非空列表彈出的列表元素,不進行任何阻塞操作。

命令:

# 對非空列表進行操作redis> RPUSH job programming(integer) 1redis> MULTIOKredis> BLPOP job 30QUEUEDredis> EXEC           # 不阻塞,立即返回1) 1) "job"   2) "programming"# 對空列表進行操作redis> LLEN job      # 空列表(integer) 0redis> MULTIOKredis> BLPOP job 30QUEUEDredis> EXEC         # 不阻塞,立即返回1) (nil)
傳回值:

如果列表為空白,返回一個nil。

否則,返回一個含有兩個元素的列表,第一個元素是被彈出元素所屬的key,第二個元素是被彈出元素的值。

模式:事件提醒

有時候,為了等待一個新元素到達資料中,需要使用輪詢的方式進行資料探查。

另一種更好的方式是,使用系統提供的阻塞原語,在新元素到達時立即進行處理,而新元素還沒有到達時,就一直阻塞,避免輪詢佔用資源。

對於redis,我們似乎需要一個阻塞版的SPOP命令,但實際上,使用BLPOP或者BRPOP就能很好的解決這個問題。

使用元素用戶端(消費者)可以執行類似以下的代碼:

LOOP forever    WHILE SPOP(key) returns elements        ... process elements ...    END    BRPOP helper_keyEND
添加元素的用戶端 ( 生產者 ) 則執行以下代碼:

MULTI    SADD key element    LPUSH helper_key xEXEC
5.BRPOP

BRPOP key [key...] timeout

BRPOP是列表的阻塞式彈出原語。

它是RPOP命令的阻塞版本,當給定列表內沒有任何元素可供彈出的時候,串連將被BRPOP命令阻塞,直到等待逾時或發現可彈出元素為止。

當給定多個key參數時,按參數key的先後順序依次檢查各個列表,彈出第一個非空列表的尾部元素。

傳回值:

假如在指定時間內沒有任何元素被彈出,則返回一個nil和等待時間長度。

反之,返回一個含有兩個元素的列表,第一個元素是被彈出元素所屬的key,第二個元素是被彈出元素的值。

命令:

redis> LLEN course(integer) 0redis> RPUSH course algorithm001(integer) 1redis> RPUSH course c++101(integer) 2redis> BRPOP course 301) "course"             # 被彈出元素所屬的列表鍵2) "c++101"             # 被彈出的元素

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.