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