前文已經提及過Redis中對於鍵值對操作的一些命令,如DEL
、EXPIRE / PEXPIRE
、TTL / PTTL
以及EXISTS
。今天我們繼續介紹Redis中對鍵值對操作的相關命令。
TYPE
TYPE
命令用於獲取指定鍵值對的類型,返回的值有string
、list
、set
、zset
、hash
以及stream
。當鍵值對不存在時返回none
。
TYPE key
示例
redis> SET key1 "value"
OK
redis> LPUSH key2 "value"
(integer) 1
redis> SADD key3 "value"
(integer) 1
redis> TYPE key1
string
redis> TYPE key2
list
redis> TYPE key3
set
redis> TYPE key4
none
RENAME / RENAMENX
RENAME
命令用於將指定鍵名重命名,並在鍵值對不存在時返回一個錯誤。若新的鍵名已存在,將會覆蓋舊值(無論舊值是否和新值是同一類型)。當Redis版本小於等於3.2.0時,若新鍵名與舊鍵名相同將返回錯誤。
RENAME key newkey
若原鍵key
有關聯過期時間,則無論新鍵是否關聯有過期時間,都將被覆蓋。
當新鍵名已經存在時,執行RENAME
命令時會先隱式地調用DEL
操作刪除對應的鍵值對,再執行重命名的操作。
RENAMENX
命令與RENAME
相似,二者的區別爲RENAMENX
僅在新鍵名不存在的情況下才完成重命名的操作。若新鍵名newkey
已存在將會返回0
,否則在正確完成重命名操作後返回0
。同樣,當原鍵名不存在時將返回錯誤。
RENAMENX key newkey
示例
redis> SET greeting "hello"
OK
redis> RENAME greeting my-greeting
OK
redis> EXISTS greeting
(integer) 0
redis> EXISTS my-greeting
(integer) 1
redis> RENAME greeting new-greeting
(error) ERR no such key
當鍵名key1
和key2
都且類型不同時,使用RENAME
也將覆蓋key2
的值:
redis> SET key1 "value1"
OK
redis> LPUSH key2 "value2"
(integer) 1
redis> RENAME key1 key2
OK
redis> TYPE key2
string
使用RENAME
重命名關聯過期時間的鍵:
# 新鍵繼承原鍵的過期時間
redis> SET key1 EX 100
OK
redis> RENAME key1 key2
OK
redis> TTL key2
(integer) 98
# 新鍵原先的過期時間被覆蓋
redis> SET key3 EX 300
OK
redis> RENAME key2 key3
OK
redis> TTL key3
(integer) 92
使用RENAMENX
命令:
redis> SET key1 "value"
OK
redis> RENAMENX key1 key2
(integer) 1
# 新鍵名key3已存在的情況下
redis> SET key3 "value"
OK
redis> RENAMENX key2 key3
(integer) 0
PERSIST
PERSIST
命令用於移除指定鍵的過期時間。
PERSIST key
示例
redis> SET greeting "hello"
OK
redis> EXPIRE greeting 100
(integer) 1
redis> TTL greeting
(integer) 98
redis> PERSIST greeting
(integer) 1
redis> TTL greeting
(integer) -1
# 未關聯過期時間的鍵
redis> PERSIST greeting
(integer) 0
EXPIREAT / PEXPIREAT
EXPIREAT
命令與之前介紹過的EXPIRE
及PEXPIRE
命令類似,用於設置已存在的鍵值對的過期時間。與前兩個命令不同的是,EXPIREAT
和PEXPIREAT
接受的參數是以秒爲單位的Unix時間戳。當過期時間被成功設置,該命令將返回1
,反之返回0
。
EXPIREAT key timestamp
與EXPIRE
相同,若指定的過期時間戳早於當前時間,該鍵將被刪除。
PEXPIREAT
與EXPIREAT
相同,它通過傳遞的以毫秒爲單位的Unix時間戳設置過期的時間。
EXPIREAT key milliseconds-timestamp
示例
# 假設當前時間爲1577836800 (2020-01-01T00:00:00)
redis> SET greeting "hello"
OK
# 2020-01-01T00:01:40
redis> EXPIREAT greeting 1577836900
(integer) 1
redis> TTL greeting
(integer) 99
# 早於當前時間的時間戳1577836700 (2019-12-31T23:58:20)
redis> EXPIREAT greeting 1577836700
(integer) 1
redis> EXISTS greeting
(integer) 0
通過PEXPIREAT
設置毫秒爲單位的過期時間:
# 毫秒爲單位的時間戳1577836900000 (2020-01-01T00:01:40)
redis> PEXPIREAT greeting 1577836900000
(integer) 1
redis> PTTL greeting
(integer) 98805
redis> TTL greeting
(integer) 98
KEYS
KEYS
用於獲取所有符合給定模式(pattern)要求的鍵。
KEYS pattern
由於KEYS
會掃描當前數據庫中所有的鍵值對,在生產環境中應當儘量避免使用該命令。如果需要相應的功能,可以使用下面將介紹的SCAN
命令替代,或者另外使用set
保存可能需要訪問的鍵名。
KEYS
命令支持glob-style的模式,包括有:
?
代表匹配任意單個字符,例如h?llo
匹配hello
、hallo
等;*
代表匹配0個或多個任意字符,例如h*llo
匹配hello
、hllllllo
等;[characters]
匹配一個方括號內的字符,例如h[ae]llo
匹配hello
以及hallo
;[^character]
匹配一個非括號內^
符號後的字符,例如h[^e]llo
匹配hallo
、hbllo
等,但不匹配hello
;[character-character]
匹配一個方括號內兩個字符範圍內的所有字符,例如h[a-e]llo
匹配hallo
、hbllo
、hcllo
、hdllo
以及hello
。
若模式內需要保護以上提到的?
、*
、[
、]
、^
、-
字符,可以使用\
進行轉義。
示例
redis> MSET firstname John lastname Doe age 25
OK
redis> KEYS *name*
1) "firstname"
2) "lastname"
redis> KEYS a??
1) "age"
redis> KEYS *
1) "firstname"
2) "lastname"
3) "age"
SCAN
SCAN
命令用於增量式迭代元素集合,與其相似的還有SSCAN
、HSCAN
以及ZSCAN
。SCAN
用於迭代當前數據庫中的所有鍵,其它幾個分別是對集合、哈希、有序集合類型進行迭代,我們將在後續的文章中對其它幾個命令進行介紹。
增量迭代的命令每次執行只會返回少數結果,不同於KEYS
命令返回所有的結果(可能導致服務阻塞)。但是使用增量式迭代的過程中可能會發現鍵被修改的情況,它只能對返回的結果提供有限的保證。
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
SCAN
命令是一個基於遊標cursor
的迭代器,每次執行後將會返回一個新的遊標,以作爲下一輪迭代的遊標參數。一次的迭代以遊標0
爲開始,並在返回遊標0時結束,稱之爲一次完整的迭代。若在迭代的途中使用了錯誤的遊標,命令執行的結果將不能保證正確,但不會對服務器本身造成影響。
SCAN
命令將會返回一個包含兩個值的數組,數組的第一個值爲下一輪迭代的新遊標,第二個元素爲一個數組,其中包含本輪迭代遍歷到的元素。
對於SCAN
命令,以及上面提到的SCAN
族中的其它命令,只能在完整迭代下提供保證對於完整遍歷開始至結束期間都存在的所有元素,必然在某次迭代中被返回;而對於在完整迭代中不存在的元素(如迭代開始前被刪除或迭代結束後被添加的元素),必然不會被返回。
在一次完整的迭代中,一個元素可能會被多次返回,需要客戶端自己處理重複的情況。在迭代中若存在元素並非一直存在(中途添加或刪除),則不能確定是否會被返回,這是一個未定義的行爲。增量迭代的算法只能保證數據集在有界的情況下停止,若在迭代的途中不斷添加新的數據,迭代可能將用於不會結束。
SCAN
命令不能保證每次迭代返回的元素數量,返回0個元素也是被允許的,只要是返回的遊標不爲0迭代都仍未結束。對於一個較大的數據集,每次迭代可能會返回數十個元素;而對於一個較小的數據集,一次迭代可能會返回全部的元素。另外,可以通過COUNT
參數設置每次迭代返回元素的最大值。
Redis可同時正確處理來自多個客戶端的迭代請求,迭代中的遊標記錄包含了迭代的所有狀態,服務器無須另外記錄迭代的狀態。同時,客戶端也可在任意時刻停止迭代,且不會對服務器造成影響。
可選參數
MATCH
提供與KEYS
相同的模式匹配行爲,執行後將只返回符合模式的鍵。COUNT
用於設置迭代返回元素數量的最大值,默認值爲10。通常每次迭代獲取的元素數量達到指定值時將結束,但COUNT
參數僅是一個作爲提示(hint)的值。- 當遍歷一個足夠大的數據集時且未使用
MATCH
選項時,返回的結果可能略大於指定的值。 - 當遍歷一個整數集合或編碼爲壓縮列表(
ziplist
),將會在第一次迭代就返回所有元素。
- 當遍歷一個足夠大的數據集時且未使用
TYPE
Redis 6.0中新加的參數,使迭代時只遍歷指定類型的鍵。其參數允許的值爲string
、list
、set
、zset
、hash
以及stream
,即TYPE
命令可能返回的所有類型。TYPE
參數只可被用於SCAN
命令。
示例
# 設置了15個鍵,鍵名爲key1至key15
# 以0作爲遊標
# 命令返回遊標7以及包含本次被迭代的元素
redis> SCAN 0
1) "7"
2) 1) "key13"
2) "key5"
3) "key11"
4) "key6"
5) "key9"
6) "key12"
7) "key3"
8) "key4"
9) "key10"
10) "key2"
11) "key1"
12) "key7"
# 以遊標7作爲第二次迭代的新遊標
# 命令返回0,表示迭代結束
redis> SCAN 7
1) "0"
2) 1) "key15"
2) "key14"
3) "key8"
噹噹前數據庫爲空時使用SCAN
命令:
redis> SCAN 0
1) "0"
2) (empty array)
使用MATCH
參數:
redis> MSET firstname John lastname Doe age 25
OK
redis> SCAN 0 MATCH *name*
1) "0"
2) 1) "firstname"
2) "lastname"
RANDOMKEY
RANDOMKEY
命令用於隨機取出一個存在的鍵。若當前數據庫中不存在任何鍵,則返回nil
。
RANDOMKEY
示例
redis> RANDOMKEY
(nil)
redis> MSET key1 "value1" key2 "value2" key3 "value3" key4 "value4" key5 "value5"
OK
redis> RANDOMKEY
"key5"
redis> RANDOMKEY
"key1"
UNLINK
UNLINK
命令與DEL
命令相似,它被用於刪除指定鍵名中存在的鍵,並忽略不存在的鍵。此命令與DEL
命令的區別是,它在另一個線程中執行刪除的操作。其執行刪除操作時會先將需要刪除的鍵從鍵空間中移除,再異步地釋放資源。UNLINK
命令是非阻塞的刪除操作,而DEL
命令是阻塞的刪除操作,在一些較複雜的情況下可採用UNLINK
命令避免Redis阻塞(在6.0版本前Redis是單線程處理的)。
UNLINK key [key ...]
UNLINK
命令與DEL
命令相同,都將返回刪除鍵的個數。
示例
redis> SET key1 "value1"
OK
redis> SET key2 "value2"
OK
redis> UNLINK key1 key2 key3
(integer) 2
結束語
本文中介紹了Redis中對鍵進行操作的相關命令,對於Redis文檔中Keys類別下的諸如DUMP
、MOVE
、OBJECT
等命令,將會在後續介紹Redis的遷移、服務、調試等相關命令時會提及,本文中便暫時不深入介紹。
歡迎大家關注我的公衆號“風紙”,或是掃下面的二維碼關注👇