網(wǎng)站首頁 編程語言 正文
redis 為什么對數(shù)字/字符串a(chǎn)ppend操作后,編碼格式object encoding從int/embstr變成raw了
作者:liuhmmjj 更新時間: 2022-04-22 編程語言不單單int編碼類型(type是string),進行字符串操作后,會自動轉(zhuǎn)碼為raw;對普通的短字符串(長度小于等于44個字節(jié))?進行append操作后,編碼格式也會發(fā)生改變(即使操作后長度還是小于等于44個字節(jié)也會由原來的embstr變成raw)!
embstr
存儲形式將 RedisObject 對象頭和 SDS 對象連續(xù)存在一起,使用 malloc 方法一次分配。
redis 3.2之后empstr只能容納44字節(jié):
?????embstr
的最小占用空間為19(16+3),而64-19-1(結(jié)尾的\0)=44,所以empstr只能容納44字節(jié)。
但是當執(zhí)行append命令之后,即使append之后的字符串長度小于等于44字節(jié)也會轉(zhuǎn)化為raw。
例如:
?append源碼分析:
append命令執(zhí)行后會進入到 src/t_string.c下的appendCommand方法
void appendCommand(client *c) {
size_t totlen;
robj *o, *append;
o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
/* Create the key */
c->argv[2] = tryObjectEncoding(c->argv[2]);
dbAdd(c->db,c->argv[1],c->argv[2]);
incrRefCount(c->argv[2]);
totlen = stringObjectLen(c->argv[2]);
} else {
/* Key exists, check type */
if (checkType(c,o,OBJ_STRING))
return;
/* "append" is an argument, so always an sds */
append = c->argv[2];
totlen = stringObjectLen(o)+sdslen(append->ptr);
if (checkStringLength(c,totlen) != C_OK)
return;
/* Append the value */
o = dbUnshareStringValue(c->db,c->argv[1],o);
o->ptr = sdscatlen(o->ptr,append->ptr,sdslen(append->ptr));
totlen = sdslen(o->ptr);
}
signalModifiedKey(c,c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_STRING,"append",c->argv[1],c->db->id);
server.dirty++;
addReplyLongLong(c,totlen);
}
打斷點會進入到上面的dbUnshareStringValue方法
robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {
serverAssert(o->type == OBJ_STRING);
if (o->refcount != 1 || o->encoding != OBJ_ENCODING_RAW) {
robj *decoded = getDecodedObject(o);
o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));
decrRefCount(decoded);
dbOverwrite(db,key,o);
}
return o;
}
然后重點關(guān)注一下這一行:
o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));
robj *createRawStringObject(const char *ptr, size_t len) {
return createObject(OBJ_STRING, sdsnewlen(ptr,len));
}
接著進入到createObject方法
robj *createObject(int type, void *ptr) {
robj *o = zmalloc(sizeof(*o));
o->type = type;
o->encoding = OBJ_ENCODING_RAW;
o->ptr = ptr;
o->refcount = 1;
/* Set the LRU to the current lruclock (minutes resolution), or
* alternatively the LFU counter. */
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL;
} else {
o->lru = LRU_CLOCK();
}
return o;
}
從這一行o->encoding = OBJ_ENCODING_RAW;可以看到創(chuàng)建的新object的編碼格式為raw類型。
總結(jié):在對embstr對象修改時其實都是新創(chuàng)建了一個raw對象,然后對raw對象進行修改,因此,當執(zhí)行append命令之后,即使append之后的字符串長度小于等于44字節(jié)也會轉(zhuǎn)化為raw
原文鏈接:https://blog.csdn.net/u014082714/article/details/122923849
相關(guān)推薦
- 2022-12-05 Golang中的錯誤處理的示例詳解_Golang
- 2023-03-25 ASP.NET?Core按用戶等級授權(quán)的方法_實用技巧
- 2022-12-09 python淺拷貝與深拷貝使用方法詳解_python
- 2022-06-13 Python+Matplotlib繪制雙y軸圖像的示例代碼_python
- 2022-07-12 hadoop 在jps中找不到namenode的原因
- 2022-05-05 Flutter如何保證數(shù)據(jù)操作原子性詳解_Android
- 2023-01-18 RabbitMq如何做到消息的可靠性投遞_Golang
- 2022-10-19 R語言安裝以及手動安裝devtools的詳細圖文教程_R語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支