Redis數據結構之字符串
字符串
字符串(string)鍵是Redis中最基本的鍵值對類型,這種類型的鍵值對會在數據庫中把單獨的一個鍵和單獨的一個值 關聯起來,被關聯的鍵和值可以是普通的文字數據,也可以是圖片、視頻、音頻、壓縮文件等更爲複雜的二進制數據。
存儲結構
字符串類型鍵的存儲結構如下圖所示:
- 與鍵 “message” 相關聯的值是 “hello world”
- 與鍵 “number” 相關聯的值是 “10086”
- 與鍵 “homepage” 相關聯的值是 “redis.io”
- 與鍵 “redis-log.jpg” 相關聯的值是 二進制數據
Redis爲字符串類型鍵提供了一系列操作命令,通過這些命令,用戶可以:
- 爲字符串鍵設置值
- 獲取字符串鍵的值
- 在獲取舊值的同時爲字符串鍵設置新值
- 同時爲多個字符串鍵設置值,或者同時獲取多個字符串鍵的值
- 獲取字符串值的長度
- 獲取字符串值指定索引範圍內的內容,或者對字符串值指定索引範圍內的內容進行修改
- 將一些內容追加到字符串值的末尾
- 對字符串鍵存儲的整數值或者浮點數值執行加法操作或減法操作
命令
命令 | 用法及參數 | 說明 |
---|---|---|
SET | SET key value [expiration EX seconds | PX milliseconds] [NX | XX] | 爲指定的字符串鍵設置相應的值,NX 和 XX選項用來指示覆蓋規則,EX 和 PX用來指定鍵的過期時間,單位分別爲秒和毫秒 |
GET | GET key | 獲取指定鍵的值 |
MSET | MSET key value [key value…] | 設置多個鍵值對 |
MGET | MGET key [key …] | 獲取多個鍵的值 |
MSETNX | MSETNX key value [key value …] | 對多個鍵設置值,只在給定所有鍵都不存在時執行設置操作,只要有一個鍵存在則放棄執行操作 |
STRLEN | STRLEN key | 獲取指定字符串鍵的值的字節長度 |
GETRANGE | GETRANGE key start end | 獲取指定鍵的值的字符串索引區間的內容,從start 到end直接的所有內容 |
SETRANGE | SETRANGE key index substitute | 將字符串鍵的值從索引 index 開始的部分替換爲指定的內容 |
APPEND | APPEND key suffix | 爲給定鍵的值追加內容 |
INCRBY | INCRBY key increment | 適用於字符串鍵值爲整數時,針對值執行加法操作 |
DECRBY | DECRBY key decrement | 適用於字符串鍵值爲整數時,針對值執行減法操作 |
INCR | INCR key | 指定鍵的值加1,等價於 INCRBY key 1 |
DECR | DECR key | 指定鍵的值減1,等價於 DECRBY key 1 |
INCRBYFLOAT | INCRBYFLOAT key increment | 字符串鍵的浮點數值執行加法運算 |
SET命令
SET 命令可以爲指定的字符串鍵設置相應的值,在最基本的情況下,只需要向SET命令提供一個鍵和一個值即可:
SET key value
SET命令在成功後會返回OK作爲結果
改變覆蓋規則
在默認情況下,對一個已經設置了值的字符串鍵執行SET命令將導致鍵的舊值被新值覆蓋,如下所示:
127.0.0.1:6379> SET msg "hello world"
OK
127.0.0.1:6379> SET msg "hello redis"
OK
在第二條命令執行完畢後,msg鍵的值將從原來的 “hello world” 變爲 “hello redis”。
從Redis 2.6.12版本開始,用戶可以通過向SET命令提供可選的 NX 選項或者 XX 選項來指示SET命令是否覆蓋一個已經存在的值:
SET key value [NX | XX]
- NX:指示SET命令只會在鍵沒有值的情況下執行設置操作,並返回OK表示成功;如果鍵已經存在,那麼SET命令將放棄執行設置操作,並返回控制 nil 表示設置失敗。
127.0.0.1:6379> SET password "123456" NX
OK -- 對尚未有值的password鍵進行設置,成功
127.0.0.1:6379> SET password "999999" NX
(nil) -- password鍵已經有值,設置失敗
- XX:指示SET命令只會在鍵已經有值的情況下執行設置操作,並返回OK表示成功;如果給定的鍵並沒有值,那麼SET命令將放棄設置操作,並返回 nil 表示設置失敗。
127.0.0.1:6379> SET homepage "redis.io" XX
(nil) -- homepage鍵沒有值,設置失敗
127.0.0.1:6379> SET homepage "redis.io"
OK -- 爲homepage鍵設置一個值
127.0.0.1:6379> SET homepage "baidu.com" XX
OK -- homepage鍵有值,設置成功
GET命令
使用GET命令,可以從數據庫中獲取指定字符串鍵的值:
GET key
給出指定的鍵即可返回對應的值,如果鍵的值不存在,則返回空 (nil)。
GETSET命令
GETSET命令就像是GET命令和SET命令的組合版本,GETSET首先獲取字符串鍵目前已有的值,接着爲鍵設置新值,最後把之前獲取的舊值返回給用戶:
GETSET key new_value
127.0.0.1:6379> GET number -- number鍵現在的值爲 "123456"
"123456"
127.0.0.1:6379> GETSET number "10086"
"123456" -- 返回舊值
127.0.0.1:6379> GET number -- number鍵的值已被更新爲 "10086"
"10086"
MSET命令
除了SET命令和GETSET命令外,Redis還提供了MSET 命令用於對字符串鍵進行設置。與SET命令和GESET命令只能對單個字符串鍵設置不同,MSET命令可以一次爲多個字符串鍵設置值:
MSET key value [key value ...]
127.0.0.1:6379> MSET msg "hello world" number "123456"
OK
127.0.0.1:6379> GET msg
"hello world"
127.0.0.1:6379> GET number
"123456"
如果給定的鍵已存在,那麼MSET命令會直接覆蓋原來的值
MGET命令
MGET命令就是一個多鍵版本的GET命令,MGET接受一個或多個字符串鍵作爲參數,並返回這些字符串鍵的值:
MGET key [key ...]
127.0.0.1:6379> MGET msg number
1) "hello world"
2) "123456"
當指定的鍵不存在時,返回空值 (nil)。
MSETNX命令
MSETNX命令與MSET一樣,都可以對多個字符串鍵設置值:
MSETNX key value [key value ...]
MSETNX與MSET的主要區別在於:MSETNX命令只會在所有給定鍵都不存在的情況下對鍵進行設置,而不會像MSET那樣直接覆蓋原值;如果給定的鍵中,即使只有一個鍵存在,那麼MSETNX命令也會放棄對所有給定鍵的設置操作。MSETNX命令成功時返回1,失敗時返回0。
127.0.0.1:6379> MGET k1 k2 k3 k4
1) (nil) -- 鍵k1、k2和k3都不存在
2) (nil)
3) (nil)
4) "hello world" -- 鍵k4已存在
127.0.0.1:6379> MSETNX k1 "one" k2 "two" k3 "three" k4 "four"
(integer) 0 -- 因爲鍵k4已存在,所以MSETNX未能執行設置操作
127.0.0.1:6379> MGET k1 k2 k3 k4
1) (nil)
2) (nil)
3) (nil)
4) "hello world"
STRLEN命令
STRLEN命令可以用來獲取指定字符串鍵存儲值的字節長度:
STRLEN key
127.0.0.1:6379> GET number
"12345"
127.0.0.1:6379> STRLEN number
(integer) 5
版本要求:STRLEN命令從Redis 2.2.0開始可用
GETRANGE
通過使用GETRANGE命令,可以獲取字符串值從 start 索引開始,直到 end 索引爲止的所有內容:
GETRANGE key start end
127.0.0.1:6379> SET msg "hello world"
OK
127.0.0.1:6379> GETRANGE msg 0 4
"hello"
127.0.0.1:6379> GETRANGE msg 6 10
"world"
GETRANGE命令的索引支持正向和反向兩種方式:
- 正向索引:類似於數組的下標一樣,從左到右依次爲 0、1、2 … n
- 反向索引:從右到左,起始值爲 -1 、-2 … -n
版本要求:GETRANGE命令從Redis 2.4.0開始可用。
SETRANGE命令
通過SETRANGE命令,用戶可以將字符串鍵的值從索引 index 開始的部分替換爲指定的新內容,被替換內容的長度取決於新內容的長度:
SETRANGE key index substitute
SETRANGE命令執行成功後,會返回字符串值當前的長度作爲結果。
127.0.0.1:6379> GET msg
"hello world"
127.0.0.1:6379> SETRANGE msg 6 "redis"
(integer) 11
127.0.0.1:6379> GET msg
"hello redis"
SETRANGE命令擴展字符串,規則如下:
- 根據新內自動擴展字符串鍵的值,以適應新內容。
- 根據給定的 index 索引擴展字符串,當給定的索引 index 超出字符串值的長度時,字符串值末尾直到索引 index - 1之間的部分將用空字節進行填充,這些字節的所有二進制位都會被設置爲 0。
127.0.0.1:6379> GET msg
"hello"
127.0.0.1:6379> STRLEN msg
(integer) 5 -- 當前字符串值的字節長度爲5
127.0.0.1:6379> SETRANGE msg 10 "world" -- 指定在索引 10 的位置處開始設置 world子串
(integer) 15
127.0.0.1:6379> GET msg
"hello\x00\x00\x00\x00\x00world"
- 先將原字符串值 “hello” 的長度擴展至15個字節長度;
- 然後將原字符串 "hello"末尾直到索引 9之間的所有字節都填充爲空字節;
- 最後再降索引10到索引14之間的內容設置爲 “world”。
上面的步驟如下圖所示:
複雜度:,其中N爲被修改內容的長度。
版本要求:SETRANGE命令從Redis 2.2.0開始可用。
APPEND命令
通過調用APPEND命令,用戶可以將給定的內容追加到字符串鍵已有的值的末尾:
APPEND key suffix
APPEND命令在執行追加操作之後,會返回字符串值當前的長度作爲命令的返回值。
127.0.0.1:6379> GET msg
"hello"
127.0.0.1:6379> APPEND msg " world"
(integer) 11
處理不存在的鍵
如果用戶給定的鍵不存在,那麼APPEND命令會先將鍵的值初始化爲空字符串 “”,然後再執行追加操作,如下所示:
127.0.0.1:6379> GET name
(nil)
127.0.0.1:6379> APPEND name "admin"
(integer) 5
127.0.0.1:6379> GET name
"admin"
複雜度:,其中N爲新追加的內容的長度
版本要求:APPEND命令從Redis 2.0.0開始可用
存儲數字值
每當用戶將一個值存儲到字符串鍵裏面的時候,Redis都會對這個值進行檢測,如果這個值能夠被解釋爲以下兩種類型的其中一種,那麼Redis就會把這個值當做數字來處理:
- 能夠使用C語言的 long long int 類型存儲的整數;
- 能夠使用C語言的 long double類型存儲的浮點數。
以下是不同類型的值,並說明了Redis對他們的解釋方式:
INCRBY 和 DECRBY命令
當字符串鍵存儲的值能夠被Redis解釋爲整數時,用戶就可以通過 INCRBY命令和DECRBY命令對被存儲的整數值執行加法或減法操作。
INCRBY key increment -- 加法操作
DECRBY key decrement -- 減法操作
127.0.0.1:6379> SET number 100
OK
127.0.0.1:6379> GET number
"100"
127.0.0.1:6379> INCRBY number 300
(integer) 400
127.0.0.1:6379> INCRBY number 25
(integer) 425
127.0.0.1:6379> GET number
"425"
127.0.0.1:6379> DECRBY number 25
(integer) 400
類型限制
當字符串鍵的值不能被Redis解釋爲整數時,對鍵執行INCRBY命令或 DECRBY命令將返回一個錯誤:
127.0.0.1:6379> SET pi 3.14
OK
127.0.0.1:6379> INCRBY pi 100 --不能對浮點數執行INCRBY命令
(error) ERR value is not an integer or out of range
127.0.0.1:6379> SET msg "hello world"
OK
127.0.0.1:6379> INCRBY msg -- 不能對字符串執行INCRBY命令
(error) ERR wrong number of arguments for 'incrby' command
127.0.0.1:6379> SET big-number 11111111111111111111111111111111111111111111
OK
127.0.0.1:6379> INCRBY big-number -- 不能對超過64位長度的整數執行INCRBY
(error) ERR value is not an integer or our of range
處理不存在的鍵
當INCRBY命令或DECRBY命令遇到不存在的鍵時,命令會先將鍵的值初始化爲0,然後再執行相應的加法或減法操作:
127.0.0.1:6379> GET x
(nil)
127.0.0.1:6379> INCRBY x 100 -- 先將鍵的值初始化爲0,然後再執行
(integer) 100
127.0.0.1:6379> GET x
"100"
複雜度:
版本要求:INCRBY命令和DECRBY命令從Redis 1.0.0開始可用。
INCR 和 DECR 命令
因爲對整數執行加 1 或減 1的操作場景經常出現,所以Redis提供了 INCR命令和DECR命令來簡化加法和減法操作:
INCR key 等價於 INCRBY key 1 -- 執行加一操作
DECR key 等價於 DECRBY key 1 -- 執行減一操作
127.0.0.1:6379> SET counter 100
OK
127.0.0.1:6379> INCR counter
(integer) 101
127.0.0.1:6379> DECR counter
(integer) 100
複雜度:
版本要求:INCR命令和DECR命令從Redis 1.0.0開始可用。
INCRBYFLOAT命令
除了用於執行整數的加法操作 INCR命令和INCRBY命令外,Redis還提供了用於執行浮點數的加法操作的 INCRBYFLOAT命令:
INCRBYFLOAT key increment
INCRBYFLOAT命令可以把一個浮點數增量加到字符串鍵存儲的數字值上面,並返回鍵在執行加法後的數字值作爲結果。
127.0.0.1:6379> SET price 10.14
OK
127.0.0.1:6379> INCRBYFLOAT price 2.55
"12.6899999999999995"
處理不存在的鍵
與INCR命令或INCRBY命令一樣,當INCRBYFLOAT命令遇到鍵不存在時,會先將鍵的值初始化爲0,然後再執行操作。
執行浮點數減法操作
Redis爲INCR命令或INCRBY命令都提供了對應的減法命令,如 DECR命令和DECRBY命令,但是並沒有爲 INCRBYFLOAT命令提供相應的減法操作命令,因此用戶只能通過給INCRBYFLOAT命令傳入負數的增量來執行減法操作。
INCRBYFLOAT 與 整數值
INCRBYFLOAT命令對於類型限制的要求比INCRBY命令和INCR命令要寬鬆得多:
- INCRBYFLOAT命令既可以用於浮點數值,也可以用於整數值
- INCRBYFLOAT命令的增量既可以是浮點數,也可以是整數
- 當INCRBYFLOAT命令的執行結果可以表示爲整數時,命令的執行結果將以整數形式存儲
127.0.0.1:6379> SET pi 1
OK
127.0.0.1:6379> GET pi
"1"
127.0.0.1:6379> INCRBYFLOAT pi 2.14
"3.14"
127.0.0.1:6379> INCRBYFLOAT pi 0.86
"4"
小數位的長度限制
雖然Redis並不限制字符串鍵存儲的浮點數的小數位長度,但是使用 INCRBYFLOAT命令處理浮點數的時候,命令最多隻會保留計算結果小數點後的17位數字,超過這個範圍的小數將被截斷。
精度問題
在上面第一個例子中,我們看到 INCRBYFLOAT命令在處理浮點數計算的時候,會有精度不準確的問題,針對這個問題,目前Redis沒有處理方案,因此,我們在確定業務需要的情況下,儘可能的通過乘以倍數的方式,將浮點數升級爲整數形式,然後使用 INCR系列命令進行計算
複雜度:
版本要求:INCRBYFLOAT命令從Redis 2.6.0開始可用。