Redis基本數(shù)據(jù)類型底層數(shù)據(jù)結構

Redis目前基本的數(shù)據(jù)類型有String、List蜈首、Set岗憋、ZSet肃晚、Hash五種,首先Redis是C語言開發(fā)的仔戈,所以底層就是用C語言封裝數(shù)據(jù)結構或者C語言本身提供的數(shù)據(jù)結構來存儲关串。redis內(nèi)部的主要數(shù)據(jù)結構主要有 簡單字符串(SDS)、雙端鏈表监徘、字典晋修、壓縮列表、跳躍表凰盔、整數(shù)集合 墓卦。Redis內(nèi)部 并沒有直接使用這些數(shù)據(jù)結構 來實現(xiàn)鍵值對數(shù)據(jù)庫,而是基于這些數(shù)據(jù)結構創(chuàng)建了一個對象系統(tǒng)户敬,這個 對象系統(tǒng) 包含了我們所熟知的五種基本類型數(shù)據(jù)落剪,也就是 字符串對象睁本、列表對象、哈希對象忠怖、集合對象和有序集合對象 這五種類型的對象呢堰。而它們每一種對象都使用到了至少一種前面所介紹的數(shù)據(jù)結構。下面介紹一下redis內(nèi)部的主要幾個數(shù)據(jù)結構 簡單字符串(SDS)脑又、雙端鏈表暮胧、壓縮列表、跳躍表 的定義问麸。然后再介紹一下redis基本的五種數(shù)據(jù)類型往衷,也就是五種類型的對象用到了上面的哪些數(shù)據(jù)結構。

redis的數(shù)據(jù)結構

SDS(Simple Dynamic String)簡單字符串

1严卖、redis定義:

Redis基本數(shù)據(jù)類型底層數(shù)據(jù)結構

2席舍、使用范圍:在redis里面,C本身的字符串只會作為字符串字面量(String literal)只用在一些不必對字符串值修改的地方哮笆,比如打印日志来颤。

而redis需要使用字符串存儲并且會修改的地方,都使用了SDS來存儲稠肘。例如Key值福铅。

3、優(yōu)點:使用SDS來存儲字符串的優(yōu)點:

  • SDS的len屬性直接記錄了長度项阴,獲取字符串長度的復雜度為O(1)滑黔。
  • C字符串本身不記錄長度容易產(chǎn)生緩存區(qū)溢出,而SDS杜絕了緩沖區(qū)的溢出环揽。
  • C字符串本身不記錄長度略荡,每次修改都要重新分配內(nèi)存,SDS減少了重新分配內(nèi)存次數(shù)歉胶。
  • 優(yōu)化了字符串縮短操作汛兜。并且可以保存任意格式的二進制數(shù)據(jù),而C字符串必須含有編碼通今。

鏈表(list)

1粥谬、鏈表:listNode結構來保存,多個listNode可以形成雙向鏈表辫塌,redis定義了list表示頭節(jié)點來持有鏈表帝嗡,下圖分別是節(jié)點listNode和鏈表list的定義。

2璃氢、redis定義:

  • 節(jié)點listNode
  • 鏈表list

3、使用范圍:鏈表在redis中用作了列表鍵狮辽、發(fā)布與訂閱一也、慢查詢巢寡、監(jiān)視器等

跳躍表(zskiplist)

1、跳躍表:是一種有序得數(shù)據(jù)結構椰苟,通過在每個節(jié)點上維持多個指向其他節(jié)點的指針抑月,從而達到快速訪問的目的,可以理解為改進版的雙端鏈表舆蝴,改進的手段是通過空間換取了時間谦絮。

2、復雜度:跳躍表支持平均O(logN)洁仗、最壞O(N)的查找復雜度层皱,大部分條件下,跳躍表的效率可以和平衡樹媲美赠潦,并且實現(xiàn)比平衡樹簡單叫胖。

  • 跳躍表節(jié)點zskiplistNode
  • 跳躍表zskiplist

3、跳躍表結構圖:

Redis基本數(shù)據(jù)類型底層數(shù)據(jù)結構

仔細觀察上圖跳躍表的結構后她奥,發(fā)現(xiàn)如果節(jié)點的層數(shù)越高瓮增,那么這個節(jié)點訪問其他節(jié)點的速度就越快。換言之哩俭,level越高绷跑,代表了這個跳躍表的查找效率可能會比較高。當然并不是絕對的凡资,因為redis每次創(chuàng)建跳躍表節(jié)點時砸捏,程序是根據(jù)冪次定律(越大的數(shù)出現(xiàn)概率越小), 生成層數(shù)高度讳苦。同時带膜,節(jié)點的順序是根據(jù)每個節(jié)點的分值排序的,如果分值相同鸳谜,那么根據(jù)對象的大小排序膝藕。

壓縮列表(ziplist)

1、壓縮列表:是redis為了節(jié)省內(nèi)存而開發(fā)的咐扭,是由一系列特殊編碼的連續(xù)內(nèi)存塊組成的順序型數(shù)據(jù)結構芭挽,一個壓縮列表的可以包含多個節(jié)點,每個節(jié)點可以保存一個字節(jié)數(shù)組或者一個整數(shù)值蝗肪。

2袜爪、壓縮列表結構圖:

Redis基本數(shù)據(jù)類型底層數(shù)據(jù)結構

3、壓縮列表特點:

  • 是一種為節(jié)省內(nèi)存開發(fā)的順序性數(shù)據(jù)結構
  • 可以包含多個節(jié)點薛闪,每個節(jié)點保存一個字節(jié)數(shù)組或者整數(shù)值
  • 添加新節(jié)點到壓縮列表辛馆,或者從壓縮列表刪除節(jié)點,可能會引發(fā)連鎖更新操作,但是機率不高

Redis五種基本數(shù)據(jù)類型

上面提到過昙篙,redis并沒有使用上面的數(shù)據(jù)結構直接用來實現(xiàn)鍵值對數(shù)據(jù)庫腊状,也就是常說的五種基本數(shù)據(jù)類型,而是創(chuàng)建了一個對象系統(tǒng)苔可,這個系統(tǒng)包含了字符串對象缴挖,列表對象、哈希對象焚辅、集合對象映屋、和有序集合對象這五種基本數(shù)據(jù)類型。這樣做有一個好處是同蜻,我們可以針對不同的場景棚点,對相同的數(shù)據(jù)類型對象使用不同的數(shù)據(jù)結構,來優(yōu)化提高效率埃仪。

redisObject對象

1乙濒、對象:redis的鍵值對都是一個redisObject結構,該結構中有三個屬性卵蛉,type類型屬性颁股、encoding編碼屬性、ptr指向底層數(shù)據(jù)結構屬性傻丝。

  • redisObject對象定義
Redis基本數(shù)據(jù)類型底層數(shù)據(jù)結構
Redis基本數(shù)據(jù)類型底層數(shù)據(jù)結構
  • 數(shù)據(jù)庫的key值都是一個string字符串對象

2甘有、編碼常量:

Redis基本數(shù)據(jù)類型底層數(shù)據(jù)結構

String類型

字符串對象的編碼是 int、raw葡缰、embstr 亏掀。參考上面的編碼常量表,也就是說字符串類型的數(shù)據(jù)底層的數(shù)據(jù)結構使用的是整數(shù)泛释、SDS滤愕、embstr編碼的SDS。

1怜校、編碼轉換

即上述幾種編碼會在何時轉換间影,也就是redis底層決定用什么存儲字符串數(shù)據(jù)?茄茁。

當int類型的編碼通過操作存儲的是字符串值魂贬,那么字符串對象的編碼將從int變?yōu)閞aw。

List類型

列表對象的編碼可以是 zipList壓縮列表linkedlist雙端鏈表 裙顽。

1付燥、編碼轉換

即上述兩種編碼會在何時轉換,也就是redis底層什么時候會用壓縮列表存儲列表數(shù)據(jù)愈犹?什么時候會使用雙端鏈表存儲列表數(shù)據(jù)键科。

當列表同時滿足以下兩個條件時,列表對象會使用zipList編碼,也就是壓縮列表

  • 列表對象保存的所有字符串元素的長度都小于64字節(jié)
  • 列表保存的元素少于512個萝嘁,

2梆掸、配置

上述兩個條件是支持配置的,也就是說我們可以redis直接讀取我們的配置牙言,來決定列表list類型底層使用什么樣的數(shù)據(jù)結構來存儲數(shù)據(jù)

  • list-max-ziplist-value
  • list-max-ziplist-entries

Set類型

集合對象使用的是 intset整數(shù)集合 (intset底層使用的是整數(shù)集合數(shù)據(jù)結構)或者 hashtable哈希表 (hashtable底層使用的是字典數(shù)據(jù)結構,我們并沒有在本文做詳細介紹怪得,有需要可以自己了解)

1咱枉、編碼轉換

當集合對象同時滿足下面兩個條件,會使用intset編碼

  • 集合對象保存的所有對象都是整數(shù)值
  • 集合對象保存的元素數(shù)量小于512個徒恋;

2蚕断、配置

上述第二個條件是支持配置的。

  • set-max-intset-entries

ZSet類型

有序集合的編碼使用的是 ziplist壓縮列表skiplist跳躍表 入挣。

注意:上面介紹skiplist的時候我們可以從結構圖中明顯看到存儲集合元素的時候亿乳,score在每個節(jié)點中式如何存儲的。那么如果ZSet使用的式ziplist壓縮列表径筏,redis怎么存儲score和value值呢葛假?其實很簡單,每個集合的元素都使用兩個節(jié)點來存儲滋恬,第一個節(jié)點保存的是成員(member)聊训,第二個元素保存的是元素的分值(score)

1、編碼轉換

當有序集合對象可以同時滿足以下兩個條件時恢氯,使用ziplist編碼

  • 有序集合的所有元素長度都小于64字節(jié)
  • 有序集合的元素數(shù)量小于128個带斑;

2、配置

上述兩個條件是支持配置的勋拟。

  • zset-max-ziplist-value
  • zset-max-ziplist-entries

Hash類型

哈希對象使用的是 ziplist壓縮列表hashtable哈希表 勋磕。(hashtable底層使用的是字典數(shù)據(jù)結構,我們并沒有在本文做詳細介紹敢靡,有需要可以自己了解)

1挂滓、編碼轉換

當哈希對象同時滿足下面兩個條件,使用ziplist壓縮列表

  • 哈希對象保存的所有鍵值對的鍵和值的字符串長度都小于64字節(jié)
  • 哈希對象保存的鍵值對的數(shù)量小于512個醋安;

2杂彭、配置

上述兩個條件是支持配置的。

  • hash-max-ziplist-value
  • hash-max-ziplist-entries
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吓揪,一起剝皮案震驚了整個濱河市亲怠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柠辞,老刑警劉巖团秽,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡习勤,警方通過查閱死者的電腦和手機踪栋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來图毕,“玉大人夷都,你說我怎么就攤上這事∮璨” “怎么了囤官?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛤虐。 經(jīng)常有香客問我党饮,道長,這世上最難降的妖魔是什么驳庭? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任刑顺,我火速辦了婚禮,結果婚禮上饲常,老公的妹妹穿的比我還像新娘蹲堂。我一直安慰自己,他們只是感情好不皆,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布贯城。 她就那樣靜靜地躺著,像睡著了一般霹娄。 火紅的嫁衣襯著肌膚如雪能犯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天犬耻,我揣著相機與錄音踩晶,去河邊找鬼。 笑死枕磁,一個胖子當著我的面吹牛渡蜻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播计济,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼茸苇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沦寂?” 一聲冷哼從身側響起学密,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎传藏,沒想到半個月后腻暮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彤守,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年哭靖,在試婚紗的時候發(fā)現(xiàn)自己被綠了具垫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡试幽,死狀恐怖筝蚕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抡草,我是刑警寧澤饰及,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站康震,受9級特大地震影響,放射性物質發(fā)生泄漏宾濒。R本人自食惡果不足惜腿短,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绘梦。 院中可真熱鬧橘忱,春花似錦、人聲如沸卸奉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽榄棵。三九已至凝颇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疹鳄,已是汗流浹背拧略。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瘪弓,地道東北人垫蛆。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像腺怯,于是被迫代替她去往敵國和親袱饭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

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