string是Redis中最經(jīng)常使用的一種結(jié)構(gòu),與c語言中的原生字符串不太一樣,Redis 使用的是一種叫做SDS的結(jié)構(gòu),simple Dynamic string 粗暴點就是簡單動態(tài)字符串,跟字面意思一樣油狂,sds能夠動態(tài)的自己增加空間,擴(kuò)容是無需使用者來操作的(相對于c 中的字符串)寸癌。
Redis 中sds有兩種版本专筷,一種是3.2之前的,這個也是那本《Redis設(shè)計與實現(xiàn)》所說的方式蒸苇,但是就現(xiàn)狀來說實效性已經(jīng)沒有那么強了磷蛹,大家注意區(qū)分。下面簡單的來看一下3.2 版本之前的:
這里以3.0.0版本為例(舊版本):src/sds.h L:41
然后再來看4.0.0 之后的版本(稱為新版本):
首先新版的根據(jù)不同的長度的字符串定義了不同的結(jié)構(gòu)溪烤,分別為:sdshdr5味咳、sdshdr8、sdshdr16檬嘀、sdshdr32槽驶、sdshdr64。
看一下里面的幾個字段:src/sds.h L:42
flags 用3bit的長度來標(biāo)注類型鸳兽,然后5bit尚未使用
len 指的是字符串的長度
alloc 指的是已分配的總長度
buf[ ]指的是就是一個普通的字符串?dāng)?shù)組掂铐,用來實際存儲的
對比而言,新版本對于舊版本對于不同長度的字符串做了優(yōu)化揍异,選取不同的數(shù)據(jù)類型uint8_t全陨、uint16_t、uint32_t 等來表示長度蒿秦,上面attribute((packed))就是用來告訴編譯器取消字節(jié)對齊的烤镐,所以說結(jié)構(gòu)體的大小其實就是按照結(jié)構(gòu)體成員實際大小相加得到的蛋济。
那Redis 中設(shè)計的這個sds 有什么優(yōu)勢和缺點呢棍鳖?
它定義的是一個typedef char *sds,sdsnew的時候?qū)嶋H上返回的是一個char *類型的指針碗旅,指向字符串的開始位置渡处,所以說
優(yōu)點:
1、我們可以把sds傳遞給任何使用char * 作為參數(shù)的函數(shù)(包括一些庫函數(shù)祟辟,而不用通過結(jié)構(gòu)體獲取地址再傳遞(相對于我們自定義的string))医瘫。
2、可以直接訪問單個字符
3旧困、分配的空間自制連續(xù)醇份,對于高速緩存的命中率更加友好稼锅。一次連續(xù)分配(Header + String + Null),對于一個sds它的各個部分總是內(nèi)存連續(xù)的僚纷。
缺點:
1矩距、sds 經(jīng)常即是參數(shù)也是返回值,所以內(nèi)部發(fā)生了什么是否重新分了空間等我們都是不知道的怖竭。
2锥债、sds 通常來說會在程序的各個位置被共享,所以我們需要在修改字符串的時候痊臭,修改所有的應(yīng)用的地方哮肚。時刻注意 一處改動導(dǎo)致其他地方失效。