篮球比分牌下方的五个横杠: Redis zipmap內存布局分析

0
Redis C/C++ Go 15394 次瀏覽

篮球比分188直播 www.703192.live   Redis 被稱為 key/value 應用中的瑞士軍刀,除了其豐富的數據結構支持,更重要的是高效的內存使用,分析源碼可以發現作者使用每一個 byte 都精打細算。在 hashtable 實現中,Redis 引入了 zipmap 數據結構,保證在 hashtable 剛創建以及元素較少時,用更少的內存來存儲,同時對查詢的效率也不會受太大的影響。下面就以源碼和例子結合的方式來分析一下 zipmap 的內存布局。

  先來看一下 zipmap 提供的和存儲相關的3個 API:

  zipmapNew:創建一個 zipmap 字符串。zipmap 創建時只有2個字節,后面會隨著 set 和 delete 操作動態擴展和收縮。

  zipmapSet: 加入新的 key/value 或者修改 zipmap 中已有 key 對應的 value。

  zipmapDel:從 zipmap 中刪除 key/value。

  下面給出一段偽代碼并分析其內存布局的變化,如下圖:

       zipmapNew ();                  

      zipmapSet (key1,value1);

      zipmapSet (key2,value2); 

      zipmapSet (key1,value3);

      zipmapDel (key2);            

      zipmapSet (key1,value4);

Redis zipmap內存布局分析

  1. zipmapNew ();

  創建一個 zipmap 結構體,包含兩個字節,第一個字節(zmlen)是長度為1個字節的無符號整數,用來保存 zipmap 當前元素個數(而非字符串長度)。當 zipmap 的元素個數大于等于254時,zmlen 將不再起作用,zipmap 需要遍歷整個字符串來獲取當前元素個數。最后一個字節為255,表示 zipmap 的結束。

  2. zipmapSet (key1, value1)

  一個元素(key/value)在 zipmap 中有5部分組成: <len><key><len><free><value>。

  <len>表示緊跟其后的 string(key 或者 value)的長度。如果 string 的長度小于254(這里代碼和注釋不統一,注釋是253,但代碼是254,以代碼為準),<len>用一個字節就可以表示(254和255有 特殊含義),如果 string 的長度大于等于254,<len>需要5個字節來表示,第一個字節設置為254,緊跟其后的4個字節通過編碼(按主機字節序)來表 示<len>的值。zipmapEncodeLength 和 zipmapDecodeLength 就是用來對<len>進行編解碼的。<key>和<value>是 char 型 string,<free>在第6步進行說明。

  3. zipmapSet (key2, value2)

  調用 zipmapSet 加入新的 key/value 時,zipmap 將根據 key2/value2的長度調用 zipmapResize 擴展空間,并將 key2/value2插入到新分配的空間。同時將 zipmap 元素的個數加1(如果<zmlen>小于254)。

  4. zipmapSet (key1,value3) 

  調用 zipmapSet 對已有的 key 修改其 value,且新的 value 值大于現有 value 占用的空間時(加 free 的空間),zipmap 將再次調用 zipmapResize 擴展空間,并調用 memmove 將 key1/vaule1之后的字符串向后順移。這里只調用一次 memmove,不會對性能有太大影響。

  5. zipmapDel (key2)

  調用 zipmapDel 刪除 key2/value2時,zipmap 將把 key2/value2之后的字符串前移,并調用 zipmapResize 收縮占用的內存空間。同時將 zipmap 元素個數減1。

  6. zipmapSet (key1, value4) 

  調用 zipmapSet 對已有的 key1 修改其 value,且新的 value 值小于現有 value 占用的空間時,zipmap 不會馬上去調用 zipmapResize 做內存空間收縮,而是將空閑字節數存入 free 中,用于后面對這個 key 再次修改 value 時,避免調用 zipmapResize(要根據新 value 的長度而定)。當然 free 的空間也不能太多,否則會造出空間的浪費。zipmap 在 free 字節數大于等于 ZIPMAP_VALUE_MAX_FREE(代碼中定義為4)時,就對 free 的空間進行收縮。

  以上就是 zipmap 內存布局和擴展收縮的過程,你可能會問 zipmapGet 豈不是O(n)的嗎?沒錯,但因為 key 和 value 都是確定長度的字符串,所以這個n是 zipmap 中元素的個數,而不是 zipmap 整個串的長度。只要在使用 zipmap 時保證元素個數不是很多,就可以在時間復雜度和空間復雜度兩方面找到很好的平衡點。redis.conf 中默認配置 hash-max-zipmap-entries 為512。

來自: rdc.taobao.com

請盡量讓自己的答案能夠對別人有幫助

1個答案

默認排序按投票排序
0

相似問題

相關經驗

相關資訊

相關文檔

{ganrao} 辽宁快乐12遗漏数据 云南11选5基本走势图 下载大众麻将新版本 黑龙江22选5中奖规则 科乐长春麻将对宝窍门 单双中特免费公开 蜂窝配资 天津11选五开奖结果一定牛 富贵棋牌游戏大厅 北京福彩快三开奖结果 财神捕鱼手机版下载 明天股市行情走势预测 30选5今天基夲走势图 九游app旧版 幸运28在哪个网站玩好 网络捕鱼赢钱游戏