Redis(七):Redis底層數(shù)據(jù)類型

1傅蹂、ziplist 壓縮列表

1.1 概述

壓縮列表是Redis為了節(jié)約內(nèi)存而開發(fā)兵迅,是一塊連續(xù)的內(nèi)存空間甜紫,元素之間緊挨著存儲(chǔ),沒有任何冗余空間艘狭。

Redis 為了節(jié)約內(nèi)存空間使用挎扰,zset 和 hash 容器對象在元素個(gè)數(shù)較少的時(shí)候,采用壓縮列表 (ziplist) 進(jìn)行存儲(chǔ)巢音。3.2.0版本之前, 當(dāng) List 容器對象在元素個(gè)數(shù)較少的時(shí)候遵倦,也采用壓縮列表 (ziplist) 進(jìn)行存儲(chǔ), 3.2.0之后 List 全部使用 quickList(快速列表)

1.2 數(shù)據(jù)結(jié)構(gòu)
image.png
struct ziplist<T> {
    int32 zlbytes; // 4 byte, 記錄整個(gè)壓縮列表占用內(nèi)存字節(jié)數(shù),在內(nèi)存分配或者計(jì)算 zlend 的位置時(shí)使用
    int32 zltail_offset; // 4 byte, 最后一個(gè)元素距離壓縮列表起始位置的偏移量,用于快速定位到最后一個(gè)節(jié)點(diǎn)
    int16 zllength; // 2 byte, 元素個(gè)數(shù)當(dāng)屬性值 < 65535 時(shí), 屬性值表示節(jié)點(diǎn)個(gè)數(shù), 當(dāng)屬性值 = 65535 時(shí), 真實(shí)節(jié)點(diǎn)個(gè)數(shù)需要遍歷壓縮列表才能計(jì)算得出
    T[] entries; // 元素節(jié)點(diǎn)列表官撼,節(jié)點(diǎn)之間挨個(gè)緊湊存儲(chǔ),無冗余空間
    int8 zlend; // 1 byte,標(biāo)志壓縮列表的結(jié)束梧躺,值恒為 0xFF
}

真正保存的數(shù)據(jù)是在元素節(jié)點(diǎn)entries中的content,每個(gè)壓縮列表的節(jié)點(diǎn)可以保存一個(gè)字節(jié)數(shù)組或者一個(gè)整數(shù)值

struct entry {
 // 前一個(gè) entry 的字節(jié)長度,
 // 前一個(gè)節(jié)點(diǎn)長度小于254字節(jié),則該屬性用一個(gè)字節(jié)表示, 否則(大于等于254字節(jié))用五個(gè)字節(jié)表示,第一個(gè)字節(jié)被設(shè)置為0xFE(254), 后四個(gè)字節(jié)表示前一個(gè)節(jié)點(diǎn)長度
    int<var> prevlen;

// 記錄了節(jié)點(diǎn)的 content 屬性所保存的數(shù)據(jù)的類型及長度
//當(dāng)屬性長度為 1 2 5 字節(jié),值最高位為 00 01 10 時(shí)表示為字節(jié)數(shù)組, 數(shù)組長度有編碼去除最高2位之后的其他位記錄, 當(dāng)屬性長度為 1 字節(jié)長, 最高位以 11 開頭表示是整數(shù)編碼,整數(shù)的類型和長度有編碼去除最高2位的其他位表示
    int<var> encoding; 

// 保存節(jié)點(diǎn)的值, 可以是一個(gè)字節(jié)數(shù)組或者整數(shù)
    optional byte[] content; 
}

2傲绣、quicklist 快速列表

2.1 概述

我們知道掠哥,鏈表中每個(gè)節(jié)點(diǎn)都會(huì)有prev 和 next 指針巩踏,每個(gè)指針占用8個(gè)字節(jié),同時(shí)续搀,其每個(gè)節(jié)點(diǎn)的內(nèi)存都是單獨(dú)分配的塞琼,這會(huì)加劇內(nèi)存的碎片化,影響內(nèi)存管理效率目代。對于redis來說屈梁,內(nèi)存是相當(dāng)寶貴的。所以有了quicklist榛了。

2.2 數(shù)據(jù)結(jié)構(gòu)
image.png

從上面可以看出在讶,quicklist其實(shí)就是ziplist作為節(jié)點(diǎn)元素組成的鏈表。

// 快速列表
struct quicklist {
    quicklistNode* head;
    quicklistNode* tail;
    long count; // 元素總數(shù)
    int nodes; // ziplist 節(jié)點(diǎn)的個(gè)數(shù)
    int compressDepth; // LZF 算法壓縮深度
    ...
}
// 快速列表節(jié)點(diǎn)
struct quicklistNode {
    quicklistNode* prev;
    quicklistNode* next;
    ziplist* zl; // 指向壓縮列表
    int32 size; // ziplist 的字節(jié)總數(shù)
    int16 count; // ziplist 中的元素?cái)?shù)量
    int2 encoding; // 存儲(chǔ)形式 2bit霜大,原生字節(jié)數(shù)組還是 LZF 壓縮存儲(chǔ)
    ...
}
2.3 zipList 長度

quicklist 內(nèi)部默認(rèn)單個(gè) ziplist 長度為 8k 字節(jié)构哺,超出了這個(gè)字節(jié)數(shù),就會(huì)新起一個(gè) ziplist战坤。

ziplist 的長度由配置參數(shù) list-max-ziplist-size 決定曙强。

3、zskiplist

3.1 概述

跳躍表是一種有序的數(shù)據(jù)結(jié)構(gòu)途茫,通過在每個(gè)節(jié)點(diǎn)中維持多個(gè)指向其他節(jié)點(diǎn)的指針碟嘴,從而達(dá)到快速訪問節(jié)點(diǎn)的目的
大部分情況下, 跳躍表的效率可以和平衡樹相媲美
Redis中只在兩處用到了跳躍表,一個(gè)是實(shí)現(xiàn)有序集合囊卜,另一個(gè)是 集群節(jié)點(diǎn)中用作內(nèi)部數(shù)據(jù)結(jié)構(gòu)

3.2 數(shù)據(jù)結(jié)構(gòu)
image.png
typedef struct zset {
    dict *dict; // 字典
    zskiplist *zsl; // 跳躍表
} zset;

typedef struct zskiplist {
    struct zskiplistNode *header, *tail; // 頭節(jié)點(diǎn) 尾節(jié)點(diǎn)
    unsigned long length; // 節(jié)點(diǎn)個(gè)數(shù)
    int level; // 最高層數(shù)
} zskiplist;


typedef struct zskiplistNode {
    sds ele; //成員
    double score; // 分值
    struct zskiplistNode *backward; // 后退指針
    struct zskiplistLevel {
        struct zskiplistNode *forward; // 前進(jìn)指針
        unsigned long span; // 跨度
    } level[]; // 多層連接指針
} zskiplistNode;

每個(gè)跳躍表節(jié)點(diǎn)都保存一個(gè)元素娜扇,并按分值從小到大排列;節(jié)點(diǎn)的object屬性保存了元素的成員栅组,score屬性保存分值雀瓢;

字典的每個(gè)鍵值對保存一個(gè)元素,字典的鍵保存元素的成員玉掸,字典的值保存分值

4刃麸、總結(jié)

在Redis的五大數(shù)據(jù)對象中,string對象是唯一個(gè)可以被其他四種數(shù)據(jù)對象作為內(nèi)嵌對象的司浪;

列表(list)泊业、哈希(hash)、集合(set)啊易、有序集合(zset)底層實(shí)現(xiàn)都用到了壓縮列表結(jié)構(gòu)脱吱,并且使用壓縮列表結(jié)構(gòu)的條件都是在元素個(gè)數(shù)比較少、字節(jié)長度較短的情況下认罩;

四種數(shù)據(jù)對象使用壓縮列表的優(yōu)點(diǎn):

  • 節(jié)約內(nèi)存,減少內(nèi)存開銷续捂,Redis是內(nèi)存型數(shù)據(jù)庫垦垂,所以一定情況下減少內(nèi)存開銷是非常有必要的宦搬。

  • 減少內(nèi)存碎片,壓縮列表的內(nèi)存塊是連續(xù)的劫拗,并分配內(nèi)存的次數(shù)一次即可间校。

  • 壓縮列表的新增、刪除页慷、查找操作的平均時(shí)間復(fù)雜度是O(N)憔足,在N再一定的范圍內(nèi),這個(gè)時(shí)間幾乎是可以忽略的酒繁,并且N的上限值是可以配置的滓彰。

  • 四種數(shù)據(jù)對象都有兩種編碼結(jié)構(gòu),靈活性增加州袒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末揭绑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子郎哭,更是在濱河造成了極大的恐慌他匪,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夸研,死亡現(xiàn)場離奇詭異邦蜜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)亥至,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門悼沈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抬闯,你說我怎么就攤上這事井辆。” “怎么了溶握?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵杯缺,是天一觀的道長。 經(jīng)常有香客問我睡榆,道長萍肆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任胀屿,我火速辦了婚禮塘揣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宿崭。我一直安慰自己亲铡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奖蔓,像睡著了一般赞草。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吆鹤,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天厨疙,我揣著相機(jī)與錄音,去河邊找鬼疑务。 笑死沾凄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的知允。 我是一名探鬼主播撒蟀,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼廊镜!你這毒婦竟也來了牙肝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嗤朴,失蹤者是張志新(化名)和其女友劉穎配椭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雹姊,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡股缸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吱雏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敦姻。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖歧杏,靈堂內(nèi)的尸體忽然破棺而出镰惦,到底是詐尸還是另有隱情,我是刑警寧澤犬绒,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布旺入,位于F島的核電站,受9級特大地震影響凯力,放射性物質(zhì)發(fā)生泄漏茵瘾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一咐鹤、第九天 我趴在偏房一處隱蔽的房頂上張望拗秘。 院中可真熱鬧,春花似錦祈惶、人聲如沸雕旨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奸腺。三九已至餐禁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間突照,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工氧吐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留讹蘑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓筑舅,卻偏偏與公主長得像座慰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子翠拣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

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

  • Redis主要支持的數(shù)據(jù)類型有5種:String 版仔,Hash ,List 误墓,Set 蛮粮,和 Sorted Set。 ...
    愛情小傻蛋閱讀 1,415評論 0 0
  • Redis的內(nèi)存優(yōu)化 聲明:本文內(nèi)容來自《Redis開發(fā)與運(yùn)維》一書第八章谜慌,如轉(zhuǎn)載請聲明然想。 Redis所有的數(shù)據(jù)都...
    meng_philip123閱讀 18,892評論 2 29
  • 你不曾離開過我 在夏日里遺漏的美麗 小心的拾起 與思念一起 是誰將你作畫,映入秋色里 映入純真的碰撞 化作無聲的言...
    07b4791da0a8閱讀 174評論 1 2
  • 過三天就要告別寒假了欣范。 一句話概括:這個(gè)寒假?zèng)]有寒假变泄,這個(gè)春節(jié)沒有春節(jié)。盡管如此恼琼,我還是感謝每一天渴望并踐行學(xué)習(xí)的...
    零度清爽閱讀 164評論 0 1
  • 秋天的山谷是格外的惹人喜歡妨蛹,茂密的叢林,進(jìn)林場都沒有路晴竞,林場的院子就位于林場的頭上蛙卤,我們來的時(shí)候的林場也就剩三兩個(gè)...
    宣巖西歌閱讀 207評論 1 2