String 字符串
字符串類型是 Redis 最基礎的數據類型,關于字符串需要特別注意:
- 首先 Redis 中所有的鍵的類型都是字符串類型,而且其他幾種數據結構也都是在字符串的基礎上構建的。
- 字符串類型的值實際可以是字符串,包含一般格式的字符串或者類似 JSON、XML 格式的字符串;數字,可以是整型或者浮點型;甚至是二進制流數據,例如圖片、音頻、視頻等。不過一個字符串的最大值不能超過 512 MB。
由于 Redis 內部存儲字符串完全是按照二進制流的形式保存的,所以 Redis 是不處理字符集編碼問題的,客戶端傳入的命令中使用的是什么字符集編碼,就存儲什么字符集編碼。
常見命令
SET
將 string 類型的 value 設置到 key 中。如果 key 之前存在,則覆蓋,無論原來的數據類型是什么。之前關于此 key 的 TTL 也全部失效。
語法:
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
命令有效版本:1.0.0 之后
時間復雜度:O(1)
選項:
- EX seconds —— 使用秒作為單位設置 key 的過期時間。
- PX milliseconds —— 使用毫秒作為單位設置 key 的過期時間。
- NX —— 只在 key 不存在時才進行設置,即如果 key 之前已經存在,設置不執行。
- XX —— 只在 key 存在時才進行設置,即如果 key 之前不存在,設置不執行。
注意:由于帶選項的 SET 命令可以被 SETNX、SETEX、PSETEX 等命令代替,所以之后的版本中,Redis 可能進行合并。
返回值: - 如果設置成功,返回 OK。
- 如果由于 SET 指定了 NX 或者 XX 但條件不滿足,SET 不會執行,并返回 (nil)。
示例:
redis> EXISTS mykey
(integer) 0
redis> SET mykey "Hello"
OK
redis> GET mykey
"Hello"
redis> SET mykey "World" NX
(nil)
redis> DEL mykey
(integer) 1
redis> EXISTS mykey
(integer) 0
redis> SET mykey "World" XX
(nil)
redis> GET mykey
(nil)
redis> SET mykey "World" NX
OK
redis> GET mykey
"World"
redis> SET mykey "Will expire in 10s" EX 10
OK
redis> GET mykey
"Will expire in 10s"
# 10秒之后
redis> GET mykey
(nil)
GET
獲取 key 對應的 value。如果 key 不存在,返回 nil。如果 value 的數據類型不是 string,會報錯。
語法:
GET key
命令有效版本:1.0.0 之后
時間復雜度:O(1)
返回值:key 對應的 value,或者 nil 當 key 不存在。
示例:
redis> GET nonexisting
(nil)
redis> SET mykey "Hello"
"OK"
redis> GET mykey
"Hello"
redis> DEL mykey
(integer) 1
redis> EXISTS mykey
(integer) 0
redis> HSET mykey name Bob
(integer) 1
redis> GET mykey
(error) WRONGTYPE Operation against a key holding the wrong kind of value
MGET
一次性獲取多個 key 的值。如果對應的 key 不存在或者對應的數據類型不是 string,返回 nil。
語法:
MGET key [key ...]
命令有效版本:1.0.0 之后
時間復雜度:O(N) N 是 key 數量
返回值:對應 value 的列表
示例:
redis> SET key1 "Hello"
OK
redis> SET key2 "World"
OK
redis> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)
MSET
一次性設置多個 key 的值。
語法:
MSET key value [key value ...]
命令有效版本:1.0.1 之后
時間復雜度:O(N) N 是 key 數量
返回值:永遠是 OK
示例:
redis> MSET key1 "Hello" key2 "World"
OK
redis> GET key1
"Hello"
redis> GET key2
"World"
如上圖所示,使用 mget 由于可以有效地減少網絡時間,所以性能相對更高。假設網絡耗時 1 毫秒,命令執行 1 毫秒,那么執行時間如下表所示。
100 次 get 和 1 次 mget 100 個鍵對比
操作 | 時間 |
---|---|
100 次 get | 100 x 1 + 100 x 0.1 = 110 毫秒 |
1 次 mget 100 個鍵 | 1 x 1 + 100 x 0.1 = 101 毫秒 |
學會使用批量操作,可以有效提高業務處理效率,但是要注意,每次批量操作所發送的鍵的數量也不是無節制的,否則可能造成單一命令執行時間過長,導致 Redis 阻塞。
SETNX
設置 key-value 但只允許在 key 之前不存在的情況下。
語法:
SETNX key value
命令有效版本:1.0.0 之后
時間復雜度:O(1)
返回值:1 表示設置成功。0 表示沒有設置。
示例:
redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"
- set key value :判斷 key 是否存在,存在或不存在均設置成功。
- set key value xx :判斷 key 是否存在,存在則設置成功,不存在則設置失敗。
- set key value nx 或者 setnx key value :判斷 key 是否存在,存在則設置失敗,不存在則設置成功。
計數命令
INCR
將 key 對應的 string 表示的數字加一。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是一個整型或者范圍超過了 64 位有符號整型,則報錯。
語法:
INCR key
命令有效版本:1.0.0 之后
時間復雜度:O(1)
返回值:integer 類型的加完后的數值。
示例:
redis> EXISTS mykey
(integer) 0
redis> INCR mykey
(integer) 1
redis> SET mykey "10"
OK
redis> INCR mykey
(integer) 11
redis> SET mykey "2342934823904890489209348230948"
OK
redis> INCR mykey
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> INCR mykey
(error) value is not an integer or out of range
INCRBY
將 key 對應的 string 表示的數字加上對應的值。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是一個整型或者范圍超過了 64 位有符號整型,則報錯。
語法:
INCRBY key decrement
命令有效版本:1.0.0 之后
時間復雜度:O(1)
返回值:integer 類型的加完后的數值。
示例:
redis> EXISTS mykey
(integer) 0
redis> INCRBY mykey 3
(integer) 3
redis> SET mykey "10"
OK
redis> INCRBY mykey 3
(integer) 13
redis> INCRBY mykey "not a number"
(error) value is not an integer or out of range
redis> SET mykey "2342934823904890489209348230948"
OK
redis> INCRBY mykey 3
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> INCRBY mykey 3
(error) value is not an integer or out of range
DECR
將 key 對應的 string 表示的數字減一。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是一個整型或者范圍超過了 64 位有符號整型,則報錯。
語法:
DECR key
命令有效版本:1.0.0 之后
時間復雜度:O(1)
返回值:integer 類型的減完后的數值。
示例:
redis> EXISTS mykey
(integer) 0
redis> DECR mykey
(integer) -1
redis> SET mykey "10"
OK
redis> DECR mykey
(integer) 9
redis> SET mykey "2342934823904890489209348230948"
OK
redis> DECR mykey
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> DECR mykey
(error) value is not an integer or out of range
DECRBY
將 key 對應的 string 表示的數字減去對應的值。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是一個整型或者范圍超過了 64 位有符號整型,則報錯。
語法:
DECRBY key decrement
命令有效版本:1.0.0 之后
時間復雜度:O(1)
返回值:integer 類型的減完后的數值。
示例:
redis> EXISTS mykey
(integer) 0
redis> DECRBY mykey 3
(integer) -3
redis> SET mykey "10"
OK
redis> DECRBY mykey 3
(integer) 7
redis> DECRBY mykey "not a number"
(error) value is not an integer or out of range
redis> SET mykey "2342934823904890489209348230948"
OK
redis> DECRBY mykey 3
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
OK
redis> DECRBY mykey 3
(error) value is not an integer or out of range
INCRBYFLOAT
將 key 對應的 string 表示的浮點數加上對應的值。如果對應的值是負數,則視為減去對應的值。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的不是 string,或者不是一個浮點數,則報錯。允許采用科學計數法表示浮點數。
語法:
INCRBYFLOAT key increment
命令有效版本:2.6.0 之后
時間復雜度:O(1)
返回值:加/減完后的數值。
示例:
redis> SET mykey 10.50
OK
redis> INCRBYFLOAT mykey 0.1
"10.6"
redis> INCRBYFLOAT mykey -5
"5.6"
redis> SET mykey 5.0e3
OK
redis> INCRBYFLOAT mykey 2.0e2
"5200"
很多存儲系統和編程語言內部使用 CAS 機制實現計數功能,會有一定的 CPU 開銷,但在 Redis 中完全不存在這個問題,因為 Redis 是單線程架構,任何命令到了 Redis 服務端都要順序執行。
其他命令
APPEND
如果 key 已經存在并且是一個 string,命令會將 value 追加到原有 string 的后邊。如果 key 不存在,則效果等同于 SET 命令。
- 語法:APPEND KEY VALUE
- 命令有效版本:2.0.0 之后
- 時間復雜度:O(1),追加的字符串一般長度較短,可視為 O(1)
- 返回值:追加完成之后 string 的長度
- 示例:
redis> EXISTS mykey
(integer) 0
redis> APPEND mykey "Hello"
(integer) 5
redis> GET mykey
"Hello"
redis> APPEND mykey " World"
(integer) 11
redis> GET mykey
"Hello World"
GETRANGE
返回 key 對應的 string 的子串,由 start 和 end 確定(左閉右閉)。可以使用負數表示倒數,-1 代表倒數第一個字符,-2 代表倒數第二個,其他的與此類似。超過范圍的偏移量會根據 string 的長度調整成正確的值。
- 語法:GETRANGE key start end
- 命令有效版本:2.4.0 之后
- 時間復雜度:O(N),N 為 [start, end] 區間的長度,由于 string 通常較短,可視為 O(1)
- 返回值:string 類型的子串
- 示例:
redis> SET mykey "This is a string"
OK
redis> GETRANGE mykey 0 3
"This"
redis> GETRANGE mykey -3 -1
"ing"
redis> GETRANGE mykey 0 -1
"This is a string"
redis> GETRANGE mykey 10 100
"string"
SETRANGE
覆蓋字符串的一部分,從指定的偏移開始。
- 語法:SETRANGE key offset value
- 命令有效版本:2.2.0 之后
- 時間復雜度:O(N),N 為 value 的長度,由于一般給的 value 較短,通常視為 O(1)
- 返回值:替換后的 string 的長度
- 示例:
redis> SET key1 "Hello World"
OK
redis> SETRANGE key1 6 "Redis"
(integer) 11
redis> GET key1
"Hello Redis"
STRLEN
獲取 key 對應的 string 的長度。當 key 存放的類似不是 string 時,報錯。
- 語法:STRLEN key
- 命令有效版本:2.2.0 之后
- 時間復雜度:O(1)
- 返回值:string 的長度。或者當 key 不存在時,返回 0
- 示例:
redis> SET mykey "Hello world"
OK
redis> STRLEN mykey
(integer) 11
redis> STRLEN nonexisting
(integer) 0
命令小結
命令 | 執行效果 | 時間復雜度 |
---|---|---|
set key value [key value…] | 設置 key 的值是 value | O(k),k 是鍵個數 |
get key | 獲取 key 的值 | O(1) |
del key [key …] | 刪除指定的 key | O(k),k 是鍵個數 |
mset key value [key value …] | 批量設置指定的 key 和 value | O(k),k 是鍵個數 |
mget key [key …] | 批量獲取 key 的值 | O(k),k 是鍵個數 |
incr key | 指定的 key 的值 +1 | O(1) |
decr key | 指定的 key 的值 -1 | O(1) |
incrby key n | 指定的 key 的值 +n | O(1) |
decrby key n | 指定的 key 的值 -n | O(1) |
incrbyfloat key n | 指定的 key 的值 +n(浮點數運算) | O(1) |
append key value | 指定的 key 的值追加 value | O(1) |
strlen key | 獲取指定 key 的值的長度 | O(1) |
setrange key offset value | 覆蓋指定 key 的從 offset 開始的部分值 | O(n),n 是字符串長度,通常視為 O(1) |
getrange key start end | 獲取指定 key 的從 start 到 end 的部分值 | O(n),n 是字符串長度,通常視為 O(1) |
內部編碼
字符串類型的內部編碼有 3 種:
- emb:8 個字節的長整型。
- embstr:小于等于 39 個字節的字符串。
- raw:大于 39 個字節的字符串。
Redis 會根據當前值的類型和長度動態決定使用哪種內部編碼實現。 - 整型示例:
127.0.0.1:6379> set key 6379
OK
127.0.0.1:6379> object encoding key
"int"
- 短字符串示例:
# 小于等于 39 個字節的字符串
127.0.0.1:6379> set key "hello"
OK
127.0.0.1:6379> object encoding key
"embstr"
- 長字符串示例:
# 大于 39 個字節的字符串
127.0.0.1:6379> set key "one string greater than 39 bytes ......."
OK
127.0.0.1:6379> object encoding key
"raw"
典型使用場景
- 緩存(Cache)功能
- 計數(Counter)功能
- 共享會話(Session)
- ?機驗證碼