天天看點

Redis常用指令詳解(中)3 string指令4 hashes4 list

2.7 type

傳回

key

所存儲的

value

的資料結構類型

傳回值

傳回目前

key

的資料類型,如果

key

不存在時傳回

none

rename

将key重命名為newkey,如果key與newkey相同,将傳回一個錯誤

如果newkey已經存在,則值将被覆寫

simple-string-reply

renamenx

當且僅當 newkey 不存在時,将 key 改名為 newkey

當 key 不存在時,傳回一個錯誤

integer-reply

:OK

  • 修改成功時,傳回 1 。
  • 如果 newkey 已經存在,傳回 0

randomkey

從目前資料庫傳回一個随機的key

3 string指令

setex

設定key對應字元串value,并且設定key在給定的seconds時間之後逾時過期。這個指令等效于執行下面的指令

SET mykey value
EXPIRE mykey seconds      

SETEX是原子的,也可以通過把上面兩個指令放到

MULTI

/

EXEC

塊中執行的方式重制。相比連續執行上面兩個指令,它更快,因為當Redis當做緩存使用時,這個操作更加常用。

OK

psetex

PSETEX

SETEX

一樣,唯一的差別是到期時間以毫秒為機關,而不是秒

getset(具有原子性)

自動将key對應到value并且傳回原來key對應的value

如果key存在但是對應的value不是字元串,就傳回錯誤

GETSET可以和INCR一起使用實作支援重置的計數功能。

舉個例子:每當有事件發生的時候,一段程式都會調用INCR給key mycounter加1,但是有時我們需要擷取計數器的值,并且自動将其重置為0。這可以通過GETSET mycounter “0”來實作:

INCR mycounter
GETSET mycounter "0"
GET mycounter      

bulk-string-reply

: 傳回之前的舊值,如果之前

Key

不存在将傳回

nil

mset

對應給定的keys到他們相應的values上。

MSET

會用新的value替換已經存在的value,就像普通的

SET

指令一樣

MSET

是原子的,是以所有給定的keys是一次性set的。用戶端不可能看到這種一部分keys被更新而另外的沒有改變的情況

:總是OK,因為MSET不會失敗

##mget

傳回所有指定的key的value。對于每個不對應string或者不存在的key,都傳回特殊值

nil

。正因為此,這個操作從來不會失敗。

array-reply

: 指定的key對應的values的list

setnx(防止set覆寫問題,具有原子性)

key

設定值為

value

如果

key

不存在,這種情況下等同set

key

存在時,什麼也不做

SETNX

是”SET if Not eXists”的簡寫

Integer reply

, 特定值

  • 1

    如果key被設定了
  • 如果key沒有被設定

msetnx

對應給定的keys到他們相應的values上

隻要有一個key已存在,MSETNX一個操作都不會執行

由于這種特性,MSETNX可以實作要麼所有的操作都成功,要麼一個都不執行,這樣可以用來設定不同的key,來表示一個唯一的對象的不同字段

MSETNX是原子的,是以所有給定的keys是一次性set的

用戶端不可能看到這種一部分keys被更新而另外的沒有改變的情況

,隻有以下兩種值:

  • 1 如果所有的key被set
  • 0 如果沒有key被set(至少其中有一個key是存在的)

incr

對存儲在指定

key

的數值執行原子的加1操作

如果指定的key不存在,那麼在執行incr操作之前,會先将它的值設定為

:執行遞增操作後

key

對應的值

##incrby

将key對應的數字加decrement

如果key不存在,操作之前,key就會被置為0。

###傳回值

: 增加之後的value值

decr

對key對應的數字做減1操作

如果key不存在,那麼在操作之前,這個key對應的值會被置為0

數字:減小之後的value

decrby

将key對應的數字減decrement

如果key不存在,操作之前,key就會被置為0

數字:減少之後的value值

apend

如果 key 已經存在,并且值為字元串,那麼這個指令會把 value 追加到原來值(value)的結尾

如果 key 不存在,那麼它将首先建立一個空字元串的key,再執行追加操作,這種情況 APPEND 将類似于 SET 操作。

Integer reply:傳回append後字元串值(value)的長度

4 hashes

3.1 hset key field value [field value …]

2.0.0提供。

時間複雜度:O(1)對每個字段/值對添加,是以 O(N) 在調用具有多個字段/值對的指令時添加 N 個字段/值對。

設定存儲在鍵到值的哈希中的字段。如果key不存在,則建立一個持有哈希的新key。如果哈希中已存在字段,則覆寫該字段。

Redis 4.0.0 起,HSET 是萬數值,允許多個字段/值對。

設定 key 指定的哈希集中指定字段的值

如果 key 指定的哈希集不存在,會建立一個新的哈希集并與 key 關聯

如果字段在哈希集中存在,它将被重寫

添加的字段數。

  • 1:如果field是一個新的字段
  • 0:如果filed原來在hash裡已存在
  • Redis常用指令詳解(中)3 string指令4 hashes4 list

3.2 hexists key field

傳回hash裡面field是否存在

, 含義如下

  • 1 hash裡面包含該field
  • 0 hash裡面不包含該field或者key不存在

3. hget key field

傳回 key 指定的哈希集中該字段所關聯的值

:該字段所關聯的值

當字段不存在或者 key 不存在時傳回nil

4. hgetall key

傳回 key 指定的哈希集中所有的字段和值

傳回值中,每個字段名的下一個是它的值,是以傳回值的長度是哈希集大小的兩倍

:哈希集中字段和值的清單。當 key 指定的哈希集不存在時傳回空清單。

hkeys key

傳回 key 指定的哈希集中所有字段的名字

:哈希集中的字段清單,當 key 指定的哈希集不存在時傳回空清單

hvals key

傳回 key 指定的哈希集中所有字段的值

:哈希集中的值的清單,當 key 指定的哈希集不存在時傳回空清單。

7. hlen

key

指定的哈希集包含的字段的數量

: 哈希集中字段的數量,當

key

指定的哈希集不存在時傳回 0

8. hmget

key

指定的哈希集中指定字段的值。

對于哈希集中不存在的每個字段,傳回

nil

值。因為不存在的keys被認為是一個空的哈希集,對一個不存在的

key

執行

HMGET

将傳回一個隻含有

nil

值的清單

array-reply:含有給定字段及其值的清單,并保持與請求相同的順序。

##9. hmset key field value [field value …]

設定 key 指定的哈希集中指定字段的值。該指令将重寫所有在哈希集中存在的字段。如果 key 指定的哈希集不存在,會建立一個新的哈希集并與 key 關聯

10. hsetnx key field value

隻在 key 指定的哈希集中不存在指定的字段時,設定字段的值

如果字段已存在,該操作無效果

4 list

雙向清單,适用于最新清單,關注清單

1. lpush

将指定的值插入清單頭

  • key 不存在, push 前會建立一個空清單
  • key 對應的值不是一個 list 的話,那麼會傳回一個錯誤

可以使用一個指令把多個元素 push 進入清單,隻需在指令末尾加上多個指定的參數

元素是從最左端的到最右端的、一個接一個被插入到 list 的頭部

lpush mylist a b c
傳回的清單是 c 為第一個元素, b 為第二個元素, a 為第三個元素      

push 後的 list 長

2. llen

傳回存儲在 key 裡的list的長度

如果 key 不存在,那麼就被看作是空list,并且傳回長度為 0

當存儲在 key 裡的值不是一個list的話,會傳回error

key對應的list的長

3. lrange key start stop

傳回存儲在 key 的清單裡指定範圍内的元素

start 和 end 偏移量都是基于0的下标,即list的第一個元素下标是0(list的表頭),第二個元素下标是1,以此類推

偏移量也可以是負數,表示偏移量是從list尾部開始計數。 例如, -1 表示清單的最後一個元素,-2 是倒數第二個,以此類推。

求範圍函數的一緻性

需要注意的是,如果你有一個list,裡面的元素是從0到100,那麼

LRANGE list 0 10

這個指令會傳回11個元素,即最右邊的那個元素也會被包含在内。 在你所使用的程式設計語言裡,這一點可能是也可能不是跟那些求範圍有關的函數都是一緻的。(像Ruby的 Range.new,Array#slice 或者Python的 range() 函數。)

超過範圍的下标

當下标超過list範圍的時候不會産生error。 如果start比list的尾部下标大的時候,會傳回一個空清單。 如果stop比list的實際尾部大的時候,Redis會當它是最後一個元素的下标。

指定範圍裡的清單元素

##4. lset key index value

設定 index 位置的list元素的值為 value

當index超出範圍時會傳回一個error

##5. lindex key index

傳回清單裡的元素的索引 index 存儲在 key 裡面。

下标是從0開始,-1 表示最後一個元素

當 key 位置的值不是一個清單的時候,會傳回一個error

bulk-reply

:請求的對應元素,或者當 index 超過範圍的時候傳回 nil

##6. lpop

移除并且傳回 key 對應的 list 的第一個元素

bulk-string-reply傳回第一個元素的值,或者當 key 不存在時傳回 nil。

7 rpop

移除并傳回存于 key 的 list 的最後一個元素。

bulk-string-reply最後一個元素的值

或 key 不存在時,傳回 nil

8 bl-pop key [key …] timeout

阻塞清單的彈出

是指令 l-pop的阻塞版本,當給定清單内沒有元素可供彈出時, 連接配接将被阻塞

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

8.1 非阻塞行為

被調用時,如果給定 key 内至少有一個非空清單,那麼彈出遇到的第一個非空清單的頭元素,并和被彈出元素所屬的清單的名字 key 一起,組成結果傳回給調用者

設 key list1 不存在,而 list2 和 list3 都是非空清單

BLPOP list1 list2 list3 0      

BLPOP 保證傳回一個存在于 list2 裡的元素(因為它是從 list1 –> list2 –> list3 這個順序查起的第一個非空清單)。

8.2 阻塞行為

如果所有給定 key 都不存在或包含空清單,則BLPOP将阻塞連接配接, 直到有另一個用戶端對給定的這些 key 的任意一個執行 LPUSH或 RPUSH。

一旦有新的資料出現在其中一個清單裡,那麼這個指令會解除阻塞狀态,并且傳回 key 和彈出的元素值。

當指令引起用戶端阻塞并且設定了一個非零的逾時參數 timeout 時, 若經過了指定的 timeout 仍沒有出現一個針對某一特定 key 的 push 操作,則用戶端會解除阻塞狀态并且傳回一個 nil 的多組合值(multi-bulk value)

timeout 參數表示的是一個指定阻塞的最大秒數的整型值

當 timeout 為 0 是表示阻塞時間無限制

8.3 什麼 key 會先被處理?是什麼用戶端?什麼元素?

  • 當用戶端為多個 key 嘗試阻塞的時候,若至少存在一個 key 擁有元素,那麼傳回的鍵值對(key/element pair)就是從左到右數第一個擁有一個或多個元素的key。

    在這種情況下用戶端不會被阻塞

  • 當多個用戶端為同一個 key 阻塞的時候,第一個被處理的用戶端是等待最長時間的那個(即第一個因為該key而阻塞的用戶端)。 一旦一個用戶端解除阻塞那麼它就不會保持任何優先級,當它因為下一個 BLPOP 指令而再次被阻塞的時候,會在處理完那些 被同個 key 阻塞的用戶端後才處理它(即從第一個被阻塞的處理到最後一個被阻塞的)。

當一個用戶端同時被多個 key 阻塞時,若多個 key 的元素同時可用(可能是因為事務或者某個Lua腳本向多個list添加元素), 那麼用戶端會解除阻塞,并使用第一個接收到 push 操作的 key(假設它擁有足夠的元素為我們的用戶端服務,因為有可能存在其他用戶端同樣是被這個key阻塞着)。 從根本上來說,在執行完每個指令之後,Redis 會把一個所有 key 都獲得資料并且至少使一個用戶端阻塞了的 list 運作一次。 這個 list 按照新資料的接收時間進行整理,即是從第一個接收資料的 key 到最後一個。在處理每個 key 的時候,隻要這個 key 裡有元素, Redis就會對所有等待這個key的用戶端按照“先進先出”(FIFO)的順序進行服務。若這個 key 是空的,或者沒有用戶端在等待這個 key, 那麼将會去處理下一個從之前的指令或事務或腳本中獲得新資料的 key,如此等等。

當多個元素被 push 進入一個 list 時 BLPOP

有時候一個 list 會在同一概念的指令的情況下接收到多個元素:

  • 像 LPUSH mylist a b c 這樣的可變 push 操作。
  • 在對一個向同一個 list 進行多次 push 操作的 MULTI 塊執行完 EXEC 語句後。

使用 Redis 2.6 或者更新的版本執行一個 Lua 腳本。

當多個元素被 push 進入一個被用戶端阻塞着的 list 的時候,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]執行後,list 包含了 c,b,a 這三個元素,是以從左邊取一個元素就會傳回 c。

相反,Redis 2.4 是以不同的方式工作的:用戶端會在 push 操作的上下文中被服務,是以當 LPUSH foo a b c 開始往 list 中 push 第一個元素,它就被傳送給用戶端A,也就是用戶端A會接收到 a(第一個被 push 的元素)。

Redis 2.4的這種行為會在複制或者持續把資料存入AOF檔案的時候引發很多問題,是以為了防止這些問題,很多更一般性的、并且在語義上更簡單的行為被引入到 Redis 2.6 中。

需要注意的是,一個Lua腳本或者一個 MULTI / EXEC 塊可能會 push 一堆元素進入一個 list 後,再 删除這個 list。 在這種情況下,被阻塞的用戶端完全不會被服務,并且隻要在執行某個單一指令、事務或者腳本後 list 中沒有出現元素,它就會被繼續阻塞下去。