W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
字符串對象的編碼可以是 int
、 raw
或者 embstr
。
如果一個字符串對象保存的是整數(shù)值, 并且這個整數(shù)值可以用 long
類型來表示, 那么字符串對象會將整數(shù)值保存在字符串對象結(jié)構(gòu)的 ptr
屬性里面(將 void*
轉(zhuǎn)換成 long
), 并將字符串對象的編碼設(shè)置為 int
。
舉個例子, 如果我們執(zhí)行以下 SET 命令, 那么服務(wù)器將創(chuàng)建一個如圖 8-1 所示的 int
編碼的字符串對象作為 number
鍵的值:
redis> SET number 10086
OK
redis> OBJECT ENCODING number
"int"
如果字符串對象保存的是一個字符串值, 并且這個字符串值的長度大于 39
字節(jié), 那么字符串對象將使用一個簡單動態(tài)字符串(SDS)來保存這個字符串值, 并將對象的編碼設(shè)置為 raw
。
舉個例子, 如果我們執(zhí)行以下命令, 那么服務(wù)器將創(chuàng)建一個如圖 8-2 所示的 raw
編碼的字符串對象作為 story
鍵的值:
redis> SET story "Long, long, long ago there lived a king ..."
OK
redis> STRLEN story
(integer) 43
redis> OBJECT ENCODING story
"raw"
如果字符串對象保存的是一個字符串值, 并且這個字符串值的長度小于等于 39
字節(jié), 那么字符串對象將使用 embstr
編碼的方式來保存這個字符串值。
embstr
編碼是專門用于保存短字符串的一種優(yōu)化編碼方式, 這種編碼和 raw
編碼一樣, 都使用 redisObject
結(jié)構(gòu)和 sdshdr
結(jié)構(gòu)來表示字符串對象, 但 raw
編碼會調(diào)用兩次內(nèi)存分配函數(shù)來分別創(chuàng)建 redisObject
結(jié)構(gòu)和 sdshdr
結(jié)構(gòu), 而 embstr
編碼則通過調(diào)用一次內(nèi)存分配函數(shù)來分配一塊連續(xù)的空間, 空間中依次包含 redisObject
和 sdshdr
兩個結(jié)構(gòu), 如圖 8-3 所示。
embstr
編碼的字符串對象在執(zhí)行命令時, 產(chǎn)生的效果和 raw
編碼的字符串對象執(zhí)行命令時產(chǎn)生的效果是相同的, 但使用 embstr
編碼的字符串對象來保存短字符串值有以下好處:
embstr
編碼將創(chuàng)建字符串對象所需的內(nèi)存分配次數(shù)從 raw
編碼的兩次降低為一次。embstr
編碼的字符串對象只需要調(diào)用一次內(nèi)存釋放函數(shù), 而釋放 raw
編碼的字符串對象需要調(diào)用兩次內(nèi)存釋放函數(shù)。embstr
編碼的字符串對象的所有數(shù)據(jù)都保存在一塊連續(xù)的內(nèi)存里面, 所以這種編碼的字符串對象比起 raw
編碼的字符串對象能夠更好地利用緩存帶來的優(yōu)勢。作為例子, 以下命令創(chuàng)建了一個 embstr
編碼的字符串對象作為 msg
鍵的值, 值對象的樣子如圖 8-4 所示:
redis> SET msg "hello"
OK
redis> OBJECT ENCODING msg
"embstr"
最后要說的是, 可以用 long double
類型表示的浮點數(shù)在 Redis 中也是作為字符串值來保存的: 如果我們要保存一個浮點數(shù)到字符串對象里面, 那么程序會先將這個浮點數(shù)轉(zhuǎn)換成字符串值, 然后再保存起轉(zhuǎn)換所得的字符串值。
舉個例子, 執(zhí)行以下代碼將創(chuàng)建一個包含 3.14
的字符串表示 "3.14"
的字符串對象:
redis> SET pi 3.14
OK
redis> OBJECT ENCODING pi
"embstr"
在有需要的時候, 程序會將保存在字符串對象里面的字符串值轉(zhuǎn)換回浮點數(shù)值, 執(zhí)行某些操作, 然后再將執(zhí)行操作所得的浮點數(shù)值轉(zhuǎn)換回字符串值, 并繼續(xù)保存在字符串對象里面。
舉個例子, 如果我們執(zhí)行以下代碼的話:
redis> INCRBYFLOAT pi 2.0
"5.14"
redis> OBJECT ENCODING pi
"embstr"
那么程序首先會取出字符串對象里面保存的字符串值 "3.14"
, 將它轉(zhuǎn)換回浮點數(shù)值 3.14
, 然后把 3.14
和 2.0
相加得出的值 5.14
轉(zhuǎn)換成字符串 "5.14"
, 并將這個 "5.14"
保存到字符串對象里面。
表 8-6 總結(jié)并列出了字符串對象保存各種不同類型的值所使用的編碼方式。
表 8-6 字符串對象保存各類型值的編碼方式
值 | 編碼 |
---|---|
可以用 long 類型保存的整數(shù)。 |
int |
可以用 long double 類型保存的浮點數(shù)。 |
embstr 或者 raw |
字符串值, 或者因為長度太大而沒辦法用 long 類型表示的整數(shù), 又或者因為長度太大而沒辦法用long double 類型表示的浮點數(shù)。 |
embstr 或者 raw |
int
編碼的字符串對象和 embstr
編碼的字符串對象在條件滿足的情況下, 會被轉(zhuǎn)換為 raw
編碼的字符串對象。
對于 int
編碼的字符串對象來說, 如果我們向?qū)ο髨?zhí)行了一些命令, 使得這個對象保存的不再是整數(shù)值, 而是一個字符串值, 那么字符串對象的編碼將從 int
變?yōu)?nbsp;raw
。
在下面的示例中, 我們通過 APPEND 命令, 向一個保存整數(shù)值的字符串對象追加了一個字符串值, 因為追加操作只能對字符串值執(zhí)行, 所以程序會先將之前保存的整數(shù)值 10086
轉(zhuǎn)換為字符串值 "10086"
, 然后再執(zhí)行追加操作, 操作的執(zhí)行結(jié)果就是一個 raw
編碼的、保存了字符串值的字符串對象:
redis> SET number 10086
OK
redis> OBJECT ENCODING number
"int"
redis> APPEND number " is a good number!"
(integer) 23
redis> GET number
"10086 is a good number!"
redis> OBJECT ENCODING number
"raw"
另外, 因為 Redis 沒有為 embstr
編碼的字符串對象編寫任何相應(yīng)的修改程序 (只有 int
編碼的字符串對象和 raw
編碼的字符串對象有這些程序), 所以 embstr
編碼的字符串對象實際上是只讀的: 當(dāng)我們對 embstr
編碼的字符串對象執(zhí)行任何修改命令時, 程序會先將對象的編碼從 embstr
轉(zhuǎn)換成 raw
, 然后再執(zhí)行修改命令; 因為這個原因, embstr
編碼的字符串對象在執(zhí)行修改命令之后, 總會變成一個 raw
編碼的字符串對象。
以下代碼展示了一個 embstr
編碼的字符串對象在執(zhí)行 APPEND 命令之后, 對象的編碼從 embstr
變?yōu)?nbsp;raw
的例子:
redis> SET msg "hello world"
OK
redis> OBJECT ENCODING msg
"embstr"
redis> APPEND msg " again!"
(integer) 18
redis> OBJECT ENCODING msg
"raw"
因為字符串鍵的值為字符串對象, 所以用于字符串鍵的所有命令都是針對字符串對象來構(gòu)建的, 表 8-7 列舉了其中一部分字符串命令, 以及這些命令在不同編碼的字符串對象下的實現(xiàn)方法。
表 8-7 字符串命令的實現(xiàn)
命令 | int 編碼的實現(xiàn)方法 |
embstr 編碼的實現(xiàn)方法 |
raw 編碼的實現(xiàn)方法 |
---|---|---|---|
SET | 使用 int 編碼保存值。 |
使用 embstr 編碼保存值。 |
使用 raw 編碼保存值。 |
GET | 拷貝對象所保存的整數(shù)值, 將這個拷貝轉(zhuǎn)換成字符串值, 然后向客戶端返回這個字符串值。 | 直接向客戶端返回字符串值。 | 直接向客戶端返回字符串值。 |
APPEND | 將對象轉(zhuǎn)換成 raw 編碼, 然后按raw 編碼的方式執(zhí)行此操作。 |
將對象轉(zhuǎn)換成 raw 編碼, 然后按raw 編碼的方式執(zhí)行此操作。 |
調(diào)用 sdscatlen 函數(shù), 將給定字符串追加到現(xiàn)有字符串的末尾。 |
INCRBYFLOAT | 取出整數(shù)值并將其轉(zhuǎn)換成 longdouble 類型的浮點數(shù), 對這個浮點數(shù)進行加法計算, 然后將得出的浮點數(shù)結(jié)果保存起來。 |
取出字符串值并嘗試將其轉(zhuǎn)換成long double 類型的浮點數(shù), 對這個浮點數(shù)進行加法計算, 然后將得出的浮點數(shù)結(jié)果保存起來。 如果字符串值不能被轉(zhuǎn)換成浮點數(shù), 那么向客戶端返回一個錯誤。 |
取出字符串值并嘗試將其轉(zhuǎn)換成 longdouble 類型的浮點數(shù), 對這個浮點數(shù)進行加法計算, 然后將得出的浮點數(shù)結(jié)果保存起來。 如果字符串值不能被轉(zhuǎn)換成浮點數(shù), 那么向客戶端返回一個錯誤。 |
INCRBY | 對整數(shù)值進行加法計算, 得出的計算結(jié)果會作為整數(shù)被保存起來。 | embstr 編碼不能執(zhí)行此命令, 向客戶端返回一個錯誤。 |
raw 編碼不能執(zhí)行此命令, 向客戶端返回一個錯誤。 |
DECRBY | 對整數(shù)值進行減法計算, 得出的計算結(jié)果會作為整數(shù)被保存起來。 | embstr 編碼不能執(zhí)行此命令, 向客戶端返回一個錯誤。 |
raw 編碼不能執(zhí)行此命令, 向客戶端返回一個錯誤。 |
STRLEN | 拷貝對象所保存的整數(shù)值, 將這個拷貝轉(zhuǎn)換成字符串值, 計算并返回這個字符串值的長度。 | 調(diào)用 sdslen 函數(shù), 返回字符串的長度。 |
調(diào)用 sdslen 函數(shù), 返回字符串的長度。 |
SETRANGE | 將對象轉(zhuǎn)換成 raw 編碼, 然后按raw 編碼的方式執(zhí)行此命令。 |
將對象轉(zhuǎn)換成 raw 編碼, 然后按raw 編碼的方式執(zhí)行此命令。 |
將字符串特定索引上的值設(shè)置為給定的字符。 |
GETRANGE | 拷貝對象所保存的整數(shù)值, 將這個拷貝轉(zhuǎn)換成字符串值, 然后取出并返回字符串指定索引上的字符。 | 直接取出并返回字符串指定索引上的字符。 | 直接取出并返回字符串指定索引上的字符。 |
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: