redis是一个键值对的数据库,说道key/value,很大程度就涉及到字符串的处理,redis是用c语言开发的,c语言自带的字符串进行字符串拓容,剪断,查看字符串长度等方面的时间复杂度均为n,这对一个经常要修改长度的字符串来说是一件很恐怖的事情,一个很简单的操作需要耗费的时间有点儿多了,这儿redis做了自己的优化。redis存储字符串用的是一个这样的结构
struct sdshdr { int len;//buf已占用长度 int free;//buf剩余可用长度 char buf[]; //实际上保留字符串的地方}; sds sdsMakeRoomFor( sds s, size_t addlen // 需要增加的空间长度){struct sdshdr *sh, *newsh;size_t free = sdsavail(s);size_t len, newlen;// 剩余空间可以满足需求,无须扩展if (free >= addlen) return s;sh = (void*) (s-(sizeof(struct sdshdr)));// 目前 buf 长度len = sdslen(s);// 新 buf 长度newlen = (len+addlen);// 如果新 buf 长度小于 SDS_MAX_PREALLOC 长度// 那么将 buf 的长度设为新 buf 长度的两倍if (newlen < SDS_MAX_PREALLOC) newlen *= 2;else newlen += SDS_MAX_PREALLOC;// 扩展长度newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);if (newsh == NULL) return NULL;newsh->free = newlen - len;return newsh->buf;}
默认初始化的时候len = 0, free = 0, buf为空,追加字符串的时候,首先判断添加的字符串的长度是否大于free,如果不大于free,就直接在buf里头填充。否则就要进行拓展,拓展的规则是,新的字符串的长度小于10241024的话,就将字符串分配2倍与所需的长度,否着分配新的长度+10241024,这就是redis在这个地方的优化