Redis學習手冊1—數據結構之字符串

字符串

字符串(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] 爲指定的字符串鍵設置相應的值,NXXX選項用來指示覆蓋規則,EXPX用來指定鍵的過期時間,單位分別爲毫秒
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 ...]

MSETNXMSET的主要區別在於: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"
  1. 先將原字符串值 “hello” 的長度擴展至15個字節長度;
  2. 然後將原字符串 "hello"末尾直到索引 9之間的所有字節都填充爲空字節;
  3. 最後再降索引10到索引14之間的內容設置爲 “world”。

上面的步驟如下圖所示:
在這裏插入圖片描述
複雜度:O(N)O(N),其中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"

複雜度:O(N)O(N),其中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"

複雜度:O(1)O(1)
版本要求: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

複雜度:O(1)O(1)
版本要求: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系列命令進行計算

複雜度:O(1)O(1)
版本要求:INCRBYFLOAT命令從Redis 2.6.0開始可用。

下一篇:Redis學習手冊2—數據結構之散列

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章