Redis dynamic strings (all strings)
String is the basic building block of Redis types.
Redis is a key-value store. All Redis keys are strings and its also the simplest value type.
Lists, sets, sorted sets and hashes are other more complex value types and even these are composed of strings.
Hacking Strings (strings )
The implementation of Redis strings is contained in sds.c
(sds
stands
for Simple Dynamic Strings).
The C structure sdshdr
declared
in sds.h
represents
a Redis string:
struct sdshdr {
long len; //string 的長度,string可以不是嚴格的字符串,因爲中間可以出現'\0',但確實是以'\0'結尾
long free; //空閒
char buf[]; //存儲實際的字符串,buf是個字符指針
};
對char buf[]來說,結構體sdshdr裏面是沒有buf的,也就是說,sizeof(struct sdshdr)==8,這是個trick,其實它可以看成是void *; 如果是寫char buf[1]的話,對齊的情況下sizeof(struct sdshdr)就是12,浪費了內存;
buf指向的是sdshdr指針+8,表示字符串的開始...
Creating Redis Strings
A new data type named sds
is
defined in sds.h
to
be a character pointer:
typedef char *sds;
sdsnewlen
function
defined in sds.c
creates
a new Redis String:
入口參數: * init //待創建的字符串,可以爲空,用於預存
size_t initlen //邏輯要村的空間大小,可以爲0,僅創建一個sdshdr。buff含一個未初始化的字符。
sds sdsnewlen(const void *init, size_t initlen) { //init爲待創建的字符串
struct sdshdr *sh;
sh = zmalloc(sizeof(struct sdshdr)+initlen+1); //1 是存"\0"用的。
#ifdef SDS_ABORT_ON_OOM
if (sh == NULL) sdsOomAbort();
#else
if (sh == NULL) return NULL;
#endif
sh->len = initlen;
sh->free = 0;//創建時沒有空閒,以後更新時free會增加,len會減少,在sdsupdatelength()中實現。
if (initlen) {
if (init) memcpy(sh->buf, init, initlen); //複製字符串
else memset(sh->buf,0,initlen); //不存在init時,全部初始化爲0
}
sh->buf[initlen] = '\0'; //結尾加爲'\0';
return (char*)sh->buf; //a trick, 通過計算可以算出sds的起始地址,對外,可以封裝sds爲一個string buffer
}
static sds sdsMakeRoomFor(sds s, size_t addlen);
若free空間不足時,以兩倍(len+addlen)進行申請。因爲調用sdsMakeRoomFor的環境通常是sds頻繁進行擴展。類似於C++中vector的動態擴展
size_t sdslen(const sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
return sh->len;
}