Redis 的命令詳解 - List 篇

相關文章redis

Redis 的命令詳解 - Key 篇
Redis 的命令詳解 - String 篇
Redis 的命令詳解 - Hash 篇
Redis 的命令詳解 - SET 篇bash

List 命令詳解

跟 Hash 相關的命令一共有 17 種,這裏只介紹經常使用的,其餘請參考官網服務器

LPUSH : 左端推入元素

起始版本 : 1.0.0
時間複雜度 : 添加一個元素爲O(1),添加多個元素爲O(N),N爲要添加的元素個數。post

將全部指定的值插入到存於 key 的列表的左端。若是 key 不存在,則在操做執行以前將其建立爲空列表。若是key對應的value不是 list 類型時,則返回錯誤。spa

推入多個元素時,多個元素從左到右依次推入左端。例如,LPUSH mylist a b c 先推入a,結果爲a。在推入b,結果爲ba。最後推入c,結果爲cbacode

語法

LPUSH key 元素1 [元素2 ...]索引

返回值

推入元素後列表的長度隊列

歷史

redis 版本 >= 2.4時,可接受多個element參數。在低於2.4的Redis版本中,只能接受一個element參數事務

LPUSHX : key 存在時,左端推入元素

起始版本 : 2.2.0
時間複雜度 : 添加一個元素爲O(1),添加多個元素爲O(N),N爲要添加的元素個數。element

只有當 key 存在,而且對應的 value 是 list 類型的時候,才執行操做。

語法

LPUSHX key 元素1 [元素2 ...]

返回值

推入元素後列表的長度

歷史

redis 版本 >= 4.0時,可接受多個element參數。在低於4.0的Redis版本中,只能接受一個element參數。

RPUSH : 右端推入元素

起始版本 : 1.0.0
時間複雜度 : 添加一個元素爲O(1),添加多個元素爲O(N),N爲要添加的元素個數。

將全部指定的值插入到存於 key 的列表的右端。若是 key 不存在,則在操做執行以前將其建立爲空列表。若是key對應的value不是 list 類型時,則返回錯誤。

推入多個元素時,多個元素從左到右依次推入右端。例如,RPUSH mylist a b c 先推入a,結果爲a。在推入b,結果爲ba。最後推入c,結果爲cba

語法

RPUSH key 元素1 [元素2 ...]

返回值

推入元素後列表的長度

歷史

redis 版本 >= 2.4時,可接受多個element參數。在低於2.4的Redis版本中,只能接受一個element參數

RPUSHX : key 存在時,右端推入元素

起始版本 : 2.2.0
時間複雜度 : 添加一個元素爲O(1),添加多個元素爲O(N),N爲要添加的元素個數。

只有當 key 存在,而且對應的 value 是 list 類型的時候,才執行操做。

語法

RPUSHX key 元素1 [元素2 ...]

返回值

推入元素後列表的長度

歷史

redis 版本 >= 4.0時,可接受多個element參數。在低於4.0的Redis版本中,只能接受一個element參數。

LPOP : 左端彈出

起始版本 : 1.0.0
時間複雜度 : O(1)

刪除(彈出)最左端的元素

當list中沒有元素時(好比元素都被彈出),key 會被刪除

語法

LPOP key

返回值

彈出元素的值,當key不存在時,返回nil

RPOP : 右端彈出

起始版本 : 1.0.0
時間複雜度 : O(1)

刪除(彈出)最右端的元素

當list中沒有元素時(好比元素都被彈出),key 會被刪除

語法

RPOP key

返回值

彈出元素的值,當key不存在時,返回nil,當list中沒有元素時,返回null

LINDEX : 返回索引處的元素

起始版本 : 1.0.0
時間複雜度 : O(N),其中N是要遍歷才能到達索引處元素的元素數。

索引從0開始,支持負索引,-1末尾最後一個元素

語法

LINDEX key index

返回值

索引處的元素,索引越界,返回null

LINSERT : 在目標元素前或後插入元素

起始版本 : 2.2.0
時間複雜度 : O(N),其中N是要遍歷才能到達插入點的元素數量,這意味着最左端的元素爲O(1)

list 存在多個相同的目標元素時,從左往右選擇第一個。

語法

LINSERT key BEFORE|AFTER 目標元素 value

目標元素爲 value 的插入點,BEFORE、AFTER 指定在目標元素的先後插入

返回值

插入操做後的list長度,當目標元素找不到時,返回 -1。

LRANGE : 獲取指定範圍的元素

起始版本 : 1.0.0
時間複雜度 : O(S + N) 其中 S 是小列表到 HEAD 的起始偏移量,大列表到最近的頭 (HEAD或TAIL) 的起始偏移量,N 是指定範圍內的元素數。

範圍獲取元素,下標從0開始,支持負下標,-1表示最右端的元素,包括開始下標,也包括結束下標

索引越界

超出範圍的索引不會產生錯誤。

若是開始下標大於列表的末尾,則返回一個空列表。

若是結束下標大於列表的實際末尾,則Redis會將其視爲列表的最後一個元素。

命令

LRANGE key 開始下標 結束下標

返回值

範圍內的元素列表

LLEN : 獲取list的長度

起始版本 : 2.2.0
時間複雜度 : O(1)

語法

LLEN key

返回值

  • list 的長度 : 正常返回時
  • 0 : key不存在
  • 錯誤 : key 對應的 value 不是 list 類型

LREM : 刪除n個指定元素

起始版本 : 2.2.0
時間複雜度 : O(N+M),其中N是列表的長度,M是刪除的元素數。

從列表中刪除 count 個 value 元素。

  • count > 0: 從頭往尾移除指定元素。
  • count < 0: 從尾往頭移除指定元素。
  • count = 0: 移除列表全部的指定元素。

好比, LREM list -2 「hello」 會從存於 list 的列表裏移除最後兩個出現的 「hello」。

須要注意的是,若是list裏沒有存在key就會被看成空list處理,因此當 key 不存在的時候,這個命令會返回 0。

語法

LREM key count 元素

返回值

已刪除元素的數量。

LSET : 更新指定下標的值

起始版本 : 1.0.0
時間複雜度 : O(N),其中N是列表的長度。將列表的第一個或最後一個元素設置爲O(1)。

更新指定下標的值, 當index超出範圍時會返回一個error。

下標從0開始,支持負下標,-1表示最右端的元素

語法

LSET key index 新值

返回值

ok

LTRIM : 裁剪 list

起始版本 : 1.0.0
時間複雜度 : O(N),其中N是要由操做刪除的元素數。

下標從0開始,支持負下標,-1表示最右端的元素,包括開始下標,也包括結束下標

例若有一個 list [01234]
LTRIM list 1 -2 的結果爲 [123]

超出範圍的索引不會產生錯誤:若是開始下標大於列表的末尾或 開始下標大於結束下標,結果將是一個空列表(空列表將致使key被刪除)。

若是 結束下標 大於列表的末尾,則Redis會將其視爲列表的最後一個元素。

LTRIM與LPUSH / RPUSH共同使用。例如:

語法

LTRIM key 開始下標 結束下標

返回值

ok

RPOPLPUSH : 右邊彈出,左邊推入

就想它的名稱同樣 R POP L PUSH,做用是將第一個 list 的最右端元素彈出,推入到 第二list的最左端,這個操做是原子行的。

咱們稱彈出元素的 list 爲源list,推入元素的 list 爲目標list

若是 源list 不存在,那麼會返回 nil 值,而且不會執行任何操做。

若是 源list目標list 存在,那麼這個操做等同於移除列表最後一個元素而且把該元素放在列表頭部, 因此這個命令也能夠看成是一個旋轉列表的命令。

語法

RPOPLPUSH 源list 目標list

返回值

彈出的元素

BRPOPLPUSH : (阻塞式)右邊彈出,左邊推入

BRPOPLPUSHRPOPLPUSH的阻塞版。

源list 存在元素時,此命令的行爲與RPOPLPUSH徹底相同。

在MULTI / EXEC塊中使用時,此命令的行爲與RPOPLPUSH徹底相同。

源list 爲空時,Redis 將阻止鏈接,直到另外一個客戶端將元素推入源list或超時到達爲止。

有關更多信息,請參見RPOPLPUSH。

語法

BRPOPLPUSH 源list 目標list timeout

timeout 是發生阻塞時的超時時間,單位秒。若是想一種阻塞下去,須要設置爲 0。

返回值

彈出的元素,若是超時,返回null

BLPOP : 左端彈出(阻塞式)

起始版本 : 2.0.0
時間複雜度 : O(1)

(阻塞式)刪除(彈出)最左端的元素

BLPOPLPOP 的阻塞版本。
二者區別

  • LPOP :key 對應的 value 中沒有元素時,返回 null
  • BLPOP :key 對應的 value 中沒有元素時,一直阻塞,直到 value 中有元素或超時。

除了上面的區別之外, BLPOP 命令還支持了多個 key。 當給定多個 key 時,按參數 key 的前後順序依次檢查各個列表,彈出第一個非空列表的最左端元素。

語法

BLPOP key1 [key2] timeout

timeout 是發生阻塞時的超時時間,單位秒。若是想一種阻塞下去,須要設置爲 0。

返回值

  • nil : 直到超時也沒有彈出元素
  • 彈出元素的key : 彈出元素的值

非阻塞場景

BLPOP 命令不是全部狀況下都會被阻塞

只要指定的 key 列表中有一個不爲null,就不會被阻塞,而是返回該key和彈出的元素。若是有多個 key 都不爲 null,依次從作往右,找到第一個不爲null的,而後返回

例如
BLPOP list1 list2 list3 0 假設 list1 爲 null。 list二、list3 不爲 null。則, 返回 list2 中最左端的元素(由於它是從 list1 –> list2 –> list3 這個順序查起的第一個非空列表)。

阻塞場景

若是全部給定的 key 都不存在或都爲空列表,那麼 BLPOP 命令將阻塞鏈接, 直到有另外一個客戶端給其中的某一個 key 添加了元素爲止。

一旦有新的數據出如今其中一個 key 中,那麼BLPOP 命令會解除阻塞狀態,而且返回該 key 和彈出的元素值。

多客戶端被同一個key阻塞後,操做的前後順序

若是有多個客戶端都在執行 BLPOP 命令。若是這些客戶端指定的 key 沒有重疊的狀況,那還好說,至關於單個客戶端執行 BLPOP 命令。但若是指定的 key 有重疊的時,操做的前後循序是什麼?

狀況1

客戶端A 、客戶端 B 調用的 BLPOP 命令中包含相同的 key,可是該 key 的 元素足夠多(>2),此時客戶端A 、客戶端 B都不會阻塞

狀況2

客戶端A 、客戶端 B 調用的 BLPOP 命令中包含相同的 key,可是該 key 的 元素只要1個,此時先來後到,先執行命令的客戶端返回,後執行命令的客戶端阻塞

狀況3

客戶端A 、客戶端 B 調用的 BLPOP 命令中包含相同的 key,可是該 key 沒有元素,客戶端A 、客戶端 B 一直阻塞,直到有元素爲止。

存在元素後,阻塞時間最長尚未超時的客戶端優先執行。

解除阻塞後,若是該客戶端又執行了該命令,須要從新排隊。

同一個客戶端被多key阻塞時的執行狀況

上面說的都是多個客戶端阻塞同一個key的狀況,再看下,同一個客戶端阻塞多個key的狀況

當一個客戶端同時被多個 key 阻塞時,若多個 key 的元素同時可用(多是由於事務或者某個Lua腳本向多個list添加元素), 那麼客戶端會解除阻塞,並使用第一個接收到 push 操做的 key(假設它擁有足夠的元素爲咱們的客戶端服務,由於有可能存在其餘客戶端一樣是被這個key阻塞着)。

從根本上來講,在執行完每一個命令以後,Redis 會把一個全部 key 都得到數據而且至少使一個客戶端阻塞了的 list 運行一次。 這個 list 按照新數據的接收時間進行整理,便是從第一個接收數據的 key 到最後一個。在處理每一個 key 的時候,只要這個 key 裏有元素, Redis就會對全部等待這個key的客戶端按照「先進先出」(FIFO)的順序進行服務。若這個 key 是空的,或者沒有客戶端在等待這個 key, 那麼將會去處理下一個從以前的命令或事務或腳本中得到新數據的 key,如此等等。

阻塞時,key 同時接收到多個元素

BLPOP阻塞時,key 有可能同時接收到多個元素,例如

  • LPUSH mylist a b c
  • 在對同一列表執行屢次推送操做的MULTI塊的EXEC以後。
  • 使用Redis 2.6或更高版本執行Lua腳本。

當多個元素被推入key中時,BLPOP 在 Redis 2.4和Redis 2.6或更高版本的行爲會有所不一樣。

對於Redis 2.6,阻塞的客戶端須要等到其餘客戶端所有push完以後纔開始解除阻塞

Client A:   BLPOP foo 0
Client B:   LPUSH foo a b c
複製代碼

若是以上狀況是在 Redis 2.6服務器或更高版本的服務器上發生的,則客戶端A將返回C,由於在LPUSH命令以後,列表包含c,b,a了該元素,所以從左側獲取元素就意味着要返回c。

相反,Redis 2.4的工做方式不一樣:在推送操做的上下文中爲阻塞客戶端提供服務。所以,只要LPUSH foo a b c開始將第一個元素a推送到list中,阻塞客戶端就會當即解除阻塞並返回a

在將數據複製或持久存儲到AOF文件中時,Redis 2.4的行爲會產生不少問題,所以Redis 2.6中引入了更爲通用和語義上更簡單的行爲來防止出現問題。

請注意,出於相同的緣由,Lua腳本或MULTI/EXEC塊可能會將元素推入列表,而後再刪除列表。在這種狀況下,只要在執行單個命令,事務或腳本以後list中沒有數據,就徹底不會爲被阻止的客戶端提供服務,而且將繼續被阻止。

實際應用

能夠利於 BLPOP 的特性,用 Redis 的 list 實現消息隊列。

BLPOP 就至關於一個監聽器,監聽 list 中的消息,有數據就返回,沒有就一直監聽

BRPOP : 右端彈出(阻塞式)

起始版本 : 2.0.0
時間複雜度 : O(1)

(阻塞式)刪除(彈出)最右端的元素

BRPOPBLPOP 語法、返回值、實現細節都相同,惟一的區別就是一個是右端彈出一個是左端彈出

相關的細節參考 BLPOP 命令

語法

BRPOP key1 [key2] timeout

timeout 是發生阻塞時的超時時間,單位秒。若是想一種阻塞下去,須要設置爲 0。

返回值

  • nil : 直到超時也沒有彈出元素
  • 彈出元素的key : 彈出元素的值
相關文章
相關標籤/搜索