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;
}