redis底層數據結構的trade-off

關于redis,通常我們的認知是他很快,拋開io設計模式及線程架構,我們單從底層數據結構了解一下redis的trade-off.

先了解一下redis的sds,sds的編碼有3種:int、raw或者embstr,當存入的的內容是Long型,redisObject的ptr指針會直接賦值為數據,這樣節省了指針空間開銷,當存入的內容是字符串,一種情況字符串小于等于44字節,redisObjec的元數據,指針和sds是同一塊內存區域,是連續的,可以避免內存碎片,這種編碼方式為embstr,當字符串大于44字節,那么sds將會是一塊獨立空間,ptr指向這塊內存。然后關于sds本身的結構,分為兩部分sds指針和sdshdr,sds是一個char類型的指針,指向buf數組首元素,sdshdr儲存頭部信息,例如len長度,作用是避免O(N)的便利而以O(1)直接獲得長度,sdshdr的另一個屬性bff數組,儲存實際數據,根據不同的字符串長度,有5,8,16,32,64五種類型,作用是節省內存。

可以看出,redis關于字符串的設計,存取時間復雜度交給本身字典的O(1),內存方面不采用c的字符串而是使用sds,首先是避免了c的字符串擴縮容的內存溢出和泄露,sds通過預分配機制,就是原本的len+新插入的數據len2,如果原本空間夠用,那么不擴容,如果len+len2 < 1Mb,那么分配

2*(len+len2),如果小于1Mb,那么分配len+len2+1M。其次是可以儲存各種類型的數據,例如音視頻數據,因為c字符串以\0代表結束,而sds是以len長度為結束,這樣便能支持更多場景的數據。

接下來結合場景以及另一個數據結構ziplist,對比一下sds,講述一下關于我們日常開發中系統設計的trade-off,壓縮列表表頭有3個字段,zlbytes,zltail和zllen,本身的entry有pre-len,len,encoding和content,通過頭部屬性,我們對表頭表尾的操作皆為O(1),而整體操作的時間復雜度便不盡人意,因為我們要遍歷。所以可以看出redis在時間空間的trade-off上面,選擇了節省內存。接下來通過一個例子,從而了解ziplist的意義

有個場景,本地有1億張圖片,對應云儲存上的圖片,我們的需求是需要快速通過本地的圖片id找到實際云上資源,那么需要把本地的id和云上的id做映射儲存起來,假如我們通過string儲存 ,根據sds本身的屬性空間開銷和redisObjec的開銷加上id數據空間開銷加上全局hash表的dictEntry:key value next三個指針,加上redis內存分配機制,jemalloc會 根據我們申請的字節數去找到最接近的2的冪次數,比如申請6字節實際會分配8字節,籠統下來,存儲一張圖片的10位id的映射需要64字節,而實際上呢,我們兩個10位id,long型實際只需要16字節。因為如果用string的話,一個鍵值對就需要一個dictEntry,如果我們采用集合,那么一個集合才消耗一個dictEntry,基于ziplist實現的數據類型有 list,hash和sorted set.

hash底層有2中數據接口,ziplist和hash表,如果我們配置好hash-max-ziplist-entries和hash-max-ziplist-value,這樣在我們的條件內,就不會轉換成hash表從而使用ziplist儲存,需要注意的地方是,pre-len是代表前一個entry的長度,如果前一個entry的長度小于255字節,那么pre-len的取值就是1字節反之5字節,所以我們要使用ziplist的時候要注意數據的增刪會引起ziplist的連鎖更新,比如本來前一個entry是小于255的 插進來一個大于255的,那么我的pre-len得變成5,假如我本身在253,那么prelen的變化會使我的大小超過255,那么從而影響到我的下一個entry.

關于skiplist,通過建立多級索引從而可以實現O(logN)的時間復雜度,思想類似二分法,不多贅述。

所以從數據結構可以看出,redis提供了在時間和空間各有優勢的數據結構,得看我們的使用場景的具體選擇從而發揮redis在時間和空間上面的優勢,舉個例子,redis的list,底層實現是雙向鏈表和壓縮列表,操作復雜度0(N),但是呢他的頭尾操作效率很高,我們就不要用它來做隨機讀取,而應當用于FIFO的場景,發揮數據結構本身的優勢,再比如sortSet,底層是skiplist,我們則應該盡量避免遍歷操作,不可避免的話,建議用scan代替

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容