Redis學習——SDS字串實現

來源:互聯網
上載者:User

標籤:

0. 前言

  這裡對Redis底層字串的實現分析,但是看完其實現還沒有完整的一個概念,即不太清楚作者為什麼要這樣子設計,只能窺知一點,需要看完redis如何使用再回頭來體會,有不足之處還望告知。

  涉及檔案:sds.h/sds.c

1.  資料結構:  

1 typedef char *sds;2 3 struct sdshdr {4     unsigned int len;    //buf中已使用的位元組數5     unsigned int free;    //buf中未使用的位元組數6     char buf[];        //緩衝區7 };

 

  這裡向外提供的api所返回的類型都是sds類型(字串),這樣的話也能夠複用一部分的C字串函數。

  這裡採用sdshdr結構,存放了字串長度資訊,保證了位元據安全,即不僅可以存放字串,也可用於存放其它位元據

2. API實現:

  只提取幾個API,該檔案完整的注釋在GitHud上(使用者名稱:jabnih)

a. sdsnewlen

  建立一個sds字串,其它幾個建立API都是基於這個API。

  建立時採用一次性分配其所需要的空間,即對於buf不進行再次分配,減少了malloc等的調用,同時在釋放的時候也減少free次數

 1 //建立一個sds字串,初始內容為init所指向的內容,buf空間為initlen大小 2 sds sdsnewlen(const void *init, size_t initlen) { 3     struct sdshdr *sh; 4  5     //這裡需要注意 6     if (init) { 7         //init不為空白,則使用malloc,所申請的空間不會初始化 8         sh = zmalloc(sizeof(struct sdshdr)+initlen+1); 9     } else {10         //init為空白,使用calloc,所申請的空間會被初始化為011         sh = zcalloc(sizeof(struct sdshdr)+initlen+1);12     }13 14     if (sh == NULL) return NULL;15 16     sh->len = initlen;17     sh->free = 0;18     //這裡如果init為NULL,則該buf的內容均為019     if (initlen && init)20         memcpy(sh->buf, init, initlen);21 22     sh->buf[initlen] = ‘\0‘;23 24     return (char*)sh->buf;25 }

 

 

b. sdsMakeRoomFor

  該API的記憶體配置策略為:在小於SDS_MAX_PREALLOC(即1M)時,會預分配出多一倍的空間,在大於該閾值時,每次只預分配多SDS_MAX_PREALLOC記憶體。

 1  //保證sds字串有足夠的剩餘未使用空間(大於或等於addlen) 2 sds sdsMakeRoomFor(sds s, size_t addlen) { 3     struct sdshdr *sh, *newsh; 4     size_t free = sdsavail(s); 5     size_t len, newlen; 6  7     //其剩餘的空間滿足addlen大小 8     if (free >= addlen) return s; 9 10     //不滿足addlen大小,需要重新分配11     len = sdslen(s);12     sh = (void*) (s-(sizeof(struct sdshdr)));13     //新空間所需使用的大小為當前sds使用的長度加上addlen14     newlen = (len+addlen);15     //如果新空間大小比設定的閾值小,則以2倍的增長速度預分配一些空間16     if (newlen < SDS_MAX_PREALLOC)17         newlen *= 2;18     else19         //比設定閾值大,則只增加PREALLOC預分配大小20         newlen += SDS_MAX_PREALLOC;21     //重新分配空間22     newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);23     if (newsh == NULL) return NULL;24 25     newsh->free = newlen - len;26     return newsh->buf;27 }

 

 

c. sdsRemoveFreeSpace

 1  //去除sds字串中未使用的空間,一般在記憶體緊張的時候使用 2 sds sdsRemoveFreeSpace(sds s) { 3     struct sdshdr *sh; 4  5     sh = (void*) (s-(sizeof(struct sdshdr))); 6     sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1); 7     sh->free = 0; 8  9     return sh->buf;10 }

 

 

d. sdsclear

1  //清空sds字串,但是不釋放空間2 void sdsclear(sds s) {3     struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));4 5     sh->free += sh->len;6     sh->len = 0;7     sh->buf[0] = ‘\0‘;8 }

 

 

3. 總結:

  1. 位元據安全

  2. 預分配空間,可以懶惰釋放,在記憶體緊張的時候也可以縮減不需要的記憶體

  3. 使用該API可以實現記憶體動態擴充(即不需要考慮記憶體空間是否足夠)

  4. 邊界檢查

Redis學習——SDS字串實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.