Redis 壓縮列表

壓縮列表(ziplist)是列表鍵和哈希鍵的底層實現之一。當一個列表鍵只包含少許列表項,而且每一個列表項是小整數或者短字符串,那麼Redis會使用壓縮列表來做爲底層的實現。數組

壓縮列表是Redis爲了節約內存而開發的,是由一系列特殊編碼的連續內存塊組成的順序型(sequential)數據結構。數據結構

結構

<zlbytes><zltail><zllen><entry><entry><zlend>ui

  1. zlbytes,uint32_t,4字節,記錄整個壓縮列表佔用的內存字節數
  2. zltail,uint32_t,4字節 ,記錄壓縮列表表位節點距離壓縮列表的起始地址有多少字節
  3. zllen,uint16_t,2字節,記錄了壓縮列表包含的節點數量,當這個數據值小於UINT16_MAX(65535)時,這個屬性的值就是壓縮列表包含節點的數量,當這個值等於UINT16_MAX時,節點的真實數量須要遍歷整個壓縮列表才能計算出
  4. entry,不固定,不固定,壓縮列表的節點主要分爲字節數組節點和整數值幾點:
  • 字節數組:可能有三種長度2^6-1字節的字節數組(加上首位2字節的類型區分位,恰好1字節長)、2^14-1字節的字節數組(加上首位2字節的類型區分位,恰好2字節長)、2^32-1字節的字節數組
  • 整數值則能夠是如下六種長度的其中一種:4位長,介於0至12之間的無符號整數、1字節長的有符號整數、3字節長的有符號整數、int16_t類型整數、int32_t類型整數、int64_t類型整數

每一個節點,都有previous_entry_length、encoding、content三個部分組成:編碼

  • previous_entry_length以字節爲單位,記錄壓縮列表的前一個節點長度,可能值爲1字節(當長度爲0~253使用1個字節)或者5字節(當長度超過253使用5字節,第一個字節固定位0xFE即十進制254,後面的4字節爲真實節點個數),這個屬性用於節點的從後向前遍歷,能夠經過這個屬性值計算出上個節點的起始位置
  • encoding記錄了節點content屬性保存數據的類型以及長度,可能有1字節、2字節、5字節長度,1字節的狀況content多是字節數組(長度小於等於63字節,encoding二進制編碼爲00XXXXXX,XXXXXX的值表示數組長度因爲只有6位長,因此最大值只能是63,若是大於63,會使用2字節或5字節的encoding編碼)也多是整數,2字節或5字節的encoding後面的content只多是字節數組,encoding頭編碼以下:

  • content保存節點的值,多是字節數組或者是整數,值得類型和長度由encoding決定,如上圖。

5. zlend表示壓縮列表的結尾,默認值爲0xFF,1字節spa

連鎖更新

    連鎖更新是指一種極端的環境下,添加或刪除節點形成後面的節點都須要進行空間重分配的狀況。ip

    假設有種極端狀況,列表有N個節點,每一個節點的previous_entry_length長度都在250~253字節之間(首節點除外,previous_entry_length爲0),即這N個節點的previous_entry_length都是1字節編碼,這時有一個長度大於253字節的節點插入到表頭,因爲以前的表頭previous_entry_length爲0,且只有1字節長度,沒法表示大於253字節的數,因此須要進行空間重分配,將previous_entry_length擴展爲5字節。內存

    這時候因爲原首節點(e1)previous_entry_length擴張,致使總體長度擴張增長了4字節,後面一個節點(e2)的previous_entry_length也要相應增長4,e2的previous_entry_length也須要從1字節擴張到5字節,這個擴張將會逐一影響後面的每一個節點都進行previous_entry_length的擴張,這種現象就叫作連鎖更新,因此最壞時間複雜度爲O(N^2);開發

    還有一種狀況即爲N個節點除首節點外previous_entry_length都是5字節,長度都爲254~257,當刪除首節點,也會形成一種連鎖收縮狀況,這種也叫連鎖更新。字符串

    因爲連鎖更新的出現須要至關特殊的狀況,因此壓縮鏈表添加,刪除操做的時間平均複雜度平均仍然是O(N),能夠放心使用。io

相關文章
相關標籤/搜索