Redis數(shù)據(jù)結(jié)構(gòu)之集合對(duì)象

Redis對(duì)象

在了解Redis數(shù)據(jù)結(jié)構(gòu)的時(shí)候我們會(huì)學(xué)習(xí)到簡(jiǎn)單動(dòng)態(tài)字符串,壓縮鏈表等俐镐。
但Redis并沒(méi)有直接使用這些數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn)鍵值對(duì)數(shù)據(jù)庫(kù),而是基于這些數(shù)據(jù)結(jié)構(gòu)創(chuàng)建了一個(gè)對(duì)象系統(tǒng)彭雾,這個(gè)系統(tǒng)包含字符串對(duì)象抄沮、列表對(duì)象、哈希對(duì)象粥庄、集合對(duì)象和有序集合對(duì)象這五種類(lèi)型的對(duì)象丧失。Redis使用對(duì)象表示鍵和值,每次新建一個(gè)鍵值對(duì)時(shí)惜互,我們就創(chuàng)建了兩個(gè)對(duì)象布讹。

集合對(duì)象

intset編碼

創(chuàng)建一個(gè)intset編碼的集合對(duì)象

127.0.0.1:6379> sadd nums 1 2 3 5
(integer) 4
127.0.0.1:6379> 
127.0.0.1:6379> type nums
set
127.0.0.1:6379> object encoding nums
"intset"

所有元素都被直接包含在一個(gè)整數(shù)集合里

content是一塊16x3字節(jié)大小的連續(xù)內(nèi)存,存了3個(gè)整數(shù)元素

hashtable編碼

當(dāng)傳入字符時(shí)训堆,變?yōu)閔ashtable編碼

127.0.0.1:6379> sadd nums "hello"
(integer) 1
127.0.0.1:6379> object encoding nums
"hashtable"

hashtable編碼的集合對(duì)象底層由字典實(shí)現(xiàn)描验。字典的鍵就是集合的內(nèi)容,值為null坑鱼。

在這里插入圖片描述

Redis字典的底層實(shí)現(xiàn)

redis字典所使用的hash表結(jié)構(gòu)

typedef struct dictht {    
    // 哈希表數(shù)組    
    dictEntry **table;    
    // 哈希表大小    
    unsigned long size;    
    //哈希表大小掩碼膘流,用于計(jì)算索引值    
    //總是等于size-1    
    unsigned long sizemask;    
    // 該哈希表已有節(jié)點(diǎn)的數(shù)量    
    unsigned long used;
} dictht;

table屬性是一個(gè)數(shù)組絮缅,數(shù)組中的每個(gè)元素都是一個(gè)指向dictEntry結(jié)構(gòu)的指針,每個(gè)dictEntry結(jié)構(gòu)保存著一個(gè)鍵值對(duì)呼股。size屬性記錄了哈希表的大小耕魄,也即是table數(shù)組的大小,而used屬性則記錄了哈希表目前已有節(jié)點(diǎn)(鍵值對(duì))的數(shù)量彭谁。sizemask屬性的值總是等于size-1吸奴,這個(gè)屬性和哈希值一起決定一個(gè)鍵應(yīng)該被放到table數(shù)組的哪個(gè)索引上面。

一個(gè)空的hash表

在這里插入圖片描述

dictEntry*[4]是一個(gè)數(shù)組缠局,數(shù)組里的每一元素都指向一個(gè)dictEntry結(jié)構(gòu)则奥,dictEntry包含3個(gè)屬性,key狭园,value逞度,發(fā)生散列沖突時(shí)指向下一個(gè)節(jié)點(diǎn)的指針next。結(jié)構(gòu)如下妙啃,看得出是使用鏈地址法解決散列沖突档泽。

在這里插入圖片描述

redis的字典是通過(guò)hash表來(lái)實(shí)現(xiàn)的

redis字典結(jié)構(gòu)

typedef struct dict {    
    // 類(lèi)型特定函數(shù)    
    dictType *type;    
    // 私有數(shù)據(jù)    
    void *privdata;   
    // 哈希表    
    dictht ht[2];    
    // rehash索引    
    //當(dāng)rehash不在進(jìn)行時(shí),值為-1    
    in trehashidx; 
    /* rehashing not in progress if rehashidx == -1 */
    } dict;

type屬性和privdata屬性是針對(duì)不同類(lèi)型的鍵值對(duì)揖赴,為創(chuàng)建多態(tài)字典而設(shè)置的:·type屬性是一個(gè)指向dictType結(jié)構(gòu)的指針馆匿,每個(gè)dictType結(jié)構(gòu)保存了一簇用于操作特定類(lèi)型鍵值對(duì)的函數(shù),Redis會(huì)為用途不同的字典設(shè)置不同的類(lèi)型特定函數(shù)燥滑〗ケ保·而privdata屬性則保存了需要傳給那些類(lèi)型特定函數(shù)的可選參數(shù)。

而redis字典保存兩個(gè)hash表铭拧,當(dāng)我們新建一個(gè)redis字典時(shí)赃蛛,默認(rèn)使用ht[0] hash表,結(jié)構(gòu)如下

在這里插入圖片描述

redis字典為什么要維護(hù)兩個(gè)hash表搀菩?

redis字典為了控制創(chuàng)建的hash表的空間開(kāi)銷(xiāo)呕臂,redis會(huì)動(dòng)態(tài)調(diào)整hash表的空間大小,當(dāng)ht[0]的長(zhǎng)度滿(mǎn)了肪跋,這里的ht[0]滿(mǎn)了并不是指dictEntry數(shù)組里面每一個(gè)元素都存儲(chǔ)了一個(gè)dictEntry歧蒋,而是dictht的used和size相同,可能有部分dictEntry會(huì)發(fā)生散列沖突的州既。
此時(shí)再向字典添加元素谜洽,此時(shí)redis字典就會(huì)進(jìn)行擴(kuò)容。
首先對(duì)ht[1進(jìn)行擴(kuò)容吴叶,擴(kuò)容的大小為比當(dāng)前當(dāng)前容量大的2的n次方阐虚,目標(biāo)大小必須為2的n次方,這樣系統(tǒng)進(jìn)行內(nèi)存分配的效率才有保證蚌卤,比如當(dāng)前容量ht[0]的容量為4实束,那么擴(kuò)容的大小就應(yīng)該為2的3次方也就是8.再將ht[0]的內(nèi)容遷移到ht[1]此時(shí)redis字典的結(jié)構(gòu)如下


在這里插入圖片描述

這樣就可以減少hash表的內(nèi)存占用贸宏,不夠的時(shí)候就擴(kuò)容hash表。這種方法雖然節(jié)約了內(nèi)存磕洪,但如果hash表已經(jīng)很長(zhǎng)了的時(shí)候,此時(shí)再擴(kuò)容它的內(nèi)存再分配的規(guī)慕肓可能就會(huì)很大析显,造成性能影響。因此签赃,為了避免rehash對(duì)服務(wù)器性能造成影響谷异,服務(wù)器不是一次性將ht[0]里面的所有鍵值對(duì)全部rehash到ht[1],而是分多次锦聊、漸進(jìn)式地將ht[0]里面的鍵值對(duì)慢慢地rehash到ht[1]歹嘹。
以下是哈希表漸進(jìn)式rehash的詳細(xì)步驟:
1)為ht[1]分配空間,讓字典同時(shí)持有ht[0]和ht[1]兩個(gè)哈希表孔庭。
2)在字典中維持一個(gè)索引計(jì)數(shù)器變量rehashidx尺上,并將它的值設(shè)置為0,表示rehash工作正式開(kāi)始圆到。
3)在rehash進(jìn)行期間怎抛,每次對(duì)字典執(zhí)行添加、刪除芽淡、查找或者更新操作時(shí)马绝,程序除了執(zhí)行指定的操作以外,還會(huì)順帶將ht[0]哈希表在rehashidx索引上的所有鍵值對(duì)rehash到ht[1]挣菲,當(dāng)rehash工作完成之后富稻,程序?qū)ehashidx屬性的加一。
4)隨著字典操作的不斷執(zhí)行白胀,最終在某個(gè)時(shí)間點(diǎn)上椭赋,ht[0]的所有鍵值對(duì)都會(huì)被rehash至ht[1],這時(shí)程序?qū)ehashidx屬性的值設(shè)為-1或杠,表示rehash操作已完成纹份。

集合的相關(guān)命令

在這里插入圖片描述

在這里插入圖片描述
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市廷痘,隨后出現(xiàn)的幾起案子蔓涧,更是在濱河造成了極大的恐慌,老刑警劉巖笋额,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件元暴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡兄猩,警方通過(guò)查閱死者的電腦和手機(jī)茉盏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)鉴未,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鸠姨,你說(shuō)我怎么就攤上這事铜秆。” “怎么了讶迁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵连茧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我巍糯,道長(zhǎng)啸驯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任祟峦,我火速辦了婚禮罚斗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宅楞。我一直安慰自己针姿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布厌衙。 她就那樣靜靜地躺著搓幌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迅箩。 梳的紋絲不亂的頭發(fā)上溉愁,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音饲趋,去河邊找鬼拐揭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛奕塑,可吹牛的內(nèi)容都是我干的堂污。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼龄砰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼盟猖!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起换棚,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤式镐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后固蚤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體娘汞,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年夕玩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了你弦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惊豺。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖禽作,靈堂內(nèi)的尸體忽然破棺而出尸昧,到底是詐尸還是另有隱情,我是刑警寧澤旷偿,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布烹俗,位于F島的核電站,受9級(jí)特大地震影響狸捅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜累提,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一尘喝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧斋陪,春花似錦朽褪、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至友题,卻和暖如春嗤堰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背度宦。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工踢匣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人戈抄。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓离唬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親划鸽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子输莺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容