參考文獻(xiàn):黃健宏《Redis設(shè)計(jì)與實(shí)現(xiàn)》
用處
整數(shù)集合是集合鍵的底層實(shí)現(xiàn)之一
當(dāng)一個(gè)集合中只包含整數(shù)值元素且元素的數(shù)量不多時(shí),redis就會(huì)使用整數(shù)集合作為集合鍵的底層實(shí)現(xiàn)
實(shí)現(xiàn)
整數(shù)集合可以保存類(lèi)型為int16_t艘款,int32_t俗慈,或者int64_t的整數(shù)值弥喉,并且會(huì)保證集合中不會(huì)出現(xiàn)重復(fù)元素
redis用intset結(jié)構(gòu)來(lái)表示一個(gè)整數(shù)集合
typedef struct intset {
// 編碼方式
uint32_t encoding;
// 集合包含的元素?cái)?shù)量
uint32_t length;
// 保存元素的數(shù)組
int8_t contents[];
}
其中主要是contents數(shù)組,用來(lái)存儲(chǔ)整數(shù)集合的每一個(gè)元素item,各個(gè)項(xiàng)在數(shù)組中按值的大小從小到大有序的排列脖祈,并且數(shù)組中不包含任何重復(fù)項(xiàng)
這里需要注意的是:雖然intset結(jié)構(gòu)將contents屬性聲明為了int8_t類(lèi)型,但實(shí)際上contengs數(shù)組并不保存任何的int8_t類(lèi)型的值刷晋,contents數(shù)組的真正類(lèi)型取決于encoding屬性的值
即這里如果計(jì)算一個(gè)整數(shù)集合中元素占用大小的話(huà)需要根據(jù)encoding屬性的值得出contents數(shù)組的item元素的類(lèi)型為什么盖高,再乘以length屬性的值即可
何為整數(shù)集合的升級(jí)
既然提到升級(jí),那么什么樣的場(chǎng)景需要進(jìn)行整數(shù)集合的升級(jí)眼虱?具體的升級(jí)又是升級(jí)什么喻奥?
前面說(shuō)到了整數(shù)集合具體的contents類(lèi)型是由encoding屬性決定的,那么我們假設(shè)一種情況:
當(dāng)一個(gè)整數(shù)集合中只有int16_t類(lèi)型的item時(shí)捏悬,那么這個(gè)整數(shù)集合的encoding值為int16_t 即可撞蚕,不需要采用int64_t類(lèi)型來(lái)浪費(fèi)內(nèi)存,
如果這個(gè)時(shí)候我們向該整數(shù)集合中添加了一個(gè)int64_t 類(lèi)型的整數(shù)过牙,比如:-2675256175807981027 這個(gè)時(shí)候現(xiàn)有的整數(shù)集合元素類(lèi)型為int16_t就放不下該元素甥厦,這個(gè)時(shí)候就需要進(jìn)行整數(shù)集合的升級(jí),升級(jí)的是整數(shù)集合中存儲(chǔ)元素的類(lèi)型
概括一下就是:
每當(dāng)我們將一個(gè)新元素添加進(jìn)整數(shù)集合里面寇钉,并且新元素的類(lèi)型比整數(shù)集合現(xiàn)有所有元素的類(lèi)型都要長(zhǎng)的時(shí)候刀疙,整數(shù)集合就需要進(jìn)行升級(jí),升級(jí)以后才能將新元素添加到整數(shù)集合中
升級(jí)步驟
根據(jù)新元素的類(lèi)型扫倡,擴(kuò)展整數(shù)集合底層數(shù)組的空間大小谦秧,為新元素分配空間
轉(zhuǎn)換底層數(shù)組中現(xiàn)有元素的類(lèi)型為新元素的類(lèi)型,并將類(lèi)型轉(zhuǎn)換后的元素放到正確的位置上撵溃,且需要維持底層數(shù)組的有序性質(zhì)
將新元素添加到底層數(shù)組中
更新整數(shù)集合的length屬性
步驟解析
假如現(xiàn)有整數(shù)集合中有三個(gè)int16_t 類(lèi)型的元素 1疚鲤, 2, 3
新元素為int32_t 類(lèi)型的65535
在第一步中缘挑,擴(kuò)展數(shù)組的空間大小是需要根據(jù)新元素的類(lèi)型計(jì)算出擴(kuò)展后的數(shù)組空間大小
那么計(jì)算出擴(kuò)展后的底層數(shù)組的占用空間大小為:4 * 32 = 128位
另一個(gè)需要注意的是數(shù)組在內(nèi)存中是一塊連續(xù)的內(nèi)存空間
數(shù)組中的下標(biāo)對(duì)應(yīng)的內(nèi)存的體現(xiàn)就是位石咬,比如128位的數(shù)組,分四個(gè)元素卖哎,那么對(duì)應(yīng)0下標(biāo)的元素占用的位就是0-31 鬼悠,相應(yīng)的1下標(biāo)對(duì)應(yīng)的位是32-63 删性,2下標(biāo)對(duì)應(yīng)的位為64-95 ,而下標(biāo)3即第四個(gè)元素對(duì)應(yīng)的位為96-127位
為什么升級(jí)
- 提升整數(shù)集合的靈活性
因?yàn)檎麛?shù)集合提供了自動(dòng)升級(jí)功能焕窝,所以我們?cè)谑褂脮r(shí)并不需要擔(dān)心出現(xiàn)類(lèi)型錯(cuò)誤蹬挺,可以隨意的將不同類(lèi)型的整數(shù)添加到整數(shù)集合中
- 節(jié)約內(nèi)存
redis設(shè)計(jì)整數(shù)集合時(shí),是可以將整數(shù)集合中元素的類(lèi)型設(shè)計(jì)成int64_t的它掂,這樣帶來(lái)結(jié)果是雖然可以向其中任意添加int16_t巴帮,int32_t,int64_t 類(lèi)型的元素不用擔(dān)心類(lèi)型錯(cuò)誤虐秋,但是弊端就是浪費(fèi)內(nèi)存榕茧,redis作為內(nèi)存數(shù)據(jù)庫(kù),對(duì)內(nèi)存尤為重視
是否支持自動(dòng)降級(jí)客给?
整數(shù)集合不支持自動(dòng)降級(jí)用押,一旦對(duì)數(shù)組進(jìn)行了升級(jí),encoding編碼屬性就會(huì)一直保存升級(jí)以后的狀態(tài)
總結(jié)
整數(shù)集合是集合鍵的底層實(shí)現(xiàn)之一
整數(shù)集合支持自動(dòng)升級(jí)策略
自動(dòng)升級(jí)帶來(lái)的好處是可以為使用整數(shù)集合的我們提供極大的靈活性靶剑,不必?fù)?dān)心類(lèi)型錯(cuò)誤以及極大的節(jié)約了內(nèi)存使用率
整數(shù)集合不支持自動(dòng)降級(jí)蜻拨,一旦升級(jí)完成,就無(wú)法降級(jí)