1. <i id="s6b2k"><small id="s6b2k"></small></i>
    <b id="s6b2k"><bdo id="s6b2k"></bdo></b>
  2. <wbr id="s6b2k"></wbr>

    Redis快速表、壓縮表和雙向鏈表(重點介紹quicklist)_Redis

    來源:腳本之家  責任編輯:小易  

    前言

    最近在看《Redis的設計與實現》這本書,寫的真的是太好了,一下子就看入迷了,謝謝作者。不過在學習的時候發現一個問題,我服務器上安裝的是Redis5.0.9版本的,而作者介紹的是Redis3.0版本的,在第一部分將數據結構與對象章節的時候,出現了一些差別,就是在redis對外暴露的list結構底層使用的數據結構問題。由于書上沒有記錄,所以就在網上查閱了些資料學習了一下, 自己再做個總結,當做自己的筆記。

    差別

    出現的差別就是,在redis3.2版本之前,它使用的是ziplist和linkedlist編碼作為列表鍵的底層實現,在它之后,就采用了一個叫做quicklist的數據結構來作其底層實現。
    先來介紹下redis3.2之前的版本的知識點:
    在使用ziplist和linkedlist作為列表鍵底層實現的時候,他們之間會有一個選擇標準:
    選擇ziplist的時候:

    列表對象保存的所有字符串元素的長度都小于64字節; 列表對象保存的元素量小于512個

    上面的是選擇ziplist作為底層實現所必須滿足的條件,如果沒滿足的話就選用linkedlist作為其底層實現。

    127.0.0.1:6379> rpush blah "hello" "world" "again"
    3
    127.0.0.1:6379> object encoding blah
    ziplist
    127.0.0.1:6379> rpush blah "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"
    4
    127.0.0.1:6379> object encoding blah
    linkedlist
    

    再來介紹下redis3.2之后的版本:

    這個涉及到quicklist這個數據結構了,書上沒有記錄,所以我查了下資料,也總結到自己的博客當中。

    我安裝的時候redis5.0.9版本的,所以上面的幾個指令執行的結果會有所不同

    127.0.0.1:6379> rpush blah "hello" "world" "again"
    3
    127.0.0.1:6379> object encoding blah
    quicklist
    127.0.0.1:6379> rpush blah "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"
    4
    127.0.0.1:6379> object encoding blah
    quicklist
    

    quicklist數據結構的介紹

    ziplist和linkedlist就不介紹了,書本上有,我們來看看quicklist。
    quicklist其實現也是依賴于ziplist和linkedlist來實現的,它是兩個結構的結合。它將ziplist來進行分段存儲,也就是分成一個個的quicklistNode節點來進行存儲。每個quicklistNode指向一個ziplist,然后quicklistNode之間是通過雙向指針來進行連接的。我們來看下大致的結構:

    看到這個結構可能會有些疑問:

    這個結構啥意思啊,為什么有的節點是ziplist,有的是quicklistZF? 為什么quicklist頭部和尾部各有兩個節點是ziplist,剩下中間的是quicklistZF? 為什么每個quicklistNode節點的ziplist內部的數據個數不一致呢?

    為什么要把底層數據結構優化成quicklist?

    在解決上面的問題之前我們先來解決一個首要的問題,也就是redis為什么要把列表鍵的底層數據結構優化成quicklist?
    其實可以從兩個方面來考慮這個原因:

    ziplist這個結構,它內部的數據存儲是一段連續的空間,這樣的話,就要求很大一塊內存空間。就比如說,我們想存儲很多的數據,但是內存中并沒有符合要求的連續的存儲空間,而是存在很多不連續的小空間(加起來可以符合要求)。 再來說說linkedlist這個結構,它數據存儲不要求連續,就可以避免上面的弊端,不過這樣以來,每個節點都分配一個一塊內存,那就有可能造成大量的內存碎片。

    綜上兩個考慮,redis在3.2版本以后就對此情況進行了優化,就出來了quicklist這個數據結構,quicklist其實就是一個分段的ziplist,為什么這么說呢?其實quicklist存儲數據基本單位是quicklistNode,每個quicklistNode的內容區就是以ziplist數據結構存儲的。也就是上面圖示展示的。

    為什么每個quicklistNode節點的ziplist內部的數據個數不一致呢?

    現在轉化到quicklist了,但是還需要考慮,quicklistNode里的ziplist里的內容處理呢?一個ziplist我需要存儲多少個數據呀?也跟上面兩個點考慮的一樣

    如果ziplist里的內容分配的越少的話,也就是往linkedlist方向發展了,就可能會產生很多的內存碎片 但要如果ziplist里的內容分配的越多的話,也會出現問題,就是需要很大一塊連續的內存空間。

    redis設計者已經給我們想好了,它的配置文件里有這樣一個參數:list-max-ziplist-size

    看到這個配置,我們來解釋下這個參數,它既可以設置正數,也可以設置負數

    當它取正數的時候,表示按照數據項個數來限定quicklist節點上的ziplist長度,比如我們設置為4,就說明每個ziplist的數據項最多不能超過5個

    當它取負數的時候,表示按照占用字節來限定quicklsit節點上的ziplist長度,這時,它只能取-1到-5這五個值,每個值的含義如下:
    1)、-5:每個quicklist節點上的ziplist大小不能超過64kb。(1kb == 1024 byte)
    2)、-4:每個quicklsit節點上的ziplist大小不能超過32kb。
    3)、-3:每個quicklsit節點上的ziplist大小不能超過16kb。
    4)、-2:每個quicklsit節點上的ziplist大小不能超過8kb。
    5)、-1:每個quicklsit節點上的ziplist大小不能超過4kb。

    所以就會出現問題所說的,ziplist內存存儲數據個數不一致的問題,我們也可以自己手動設置參數值。

    這個結構啥意思啊,為什么有的節點是ziplist,有的是quicklistZF?

    這里又出現了一個配置參數:list-compress-depth
    其實,當鏈表很長的時候,最頻繁訪問的就是兩端的數據,中間被訪問的頻率比較低,所以我們可以將中間部分節點進行壓縮,從而能夠進一步節省空間。上面說的list-compress-depth就是來設置這個的。
    這個參數的取值含義如下:

    0:是個特殊值,表示都不壓縮。這是redis的默認值

    1:表示quicklist兩端各有一個節點不被壓縮,中間節點進行壓縮

    2:表示quicklist兩端各有兩個節點不被壓縮,中間節點進行壓縮

    3:表示quicklist兩端各有三個節點不被壓縮,中間節點進行壓縮…

    以此類推

    也就是會出現問題所說的,兩端節點為ziplist,中間節點為quicklistZF

    我們看看上面的redis配置文件的默認配置。

    簡單了解源碼結構

    我通過上面這個圖來簡單說一下quicklist的存儲方式,它底層有兩個結構,一個quicklist,一個就是quicklistNode。下面是我找的源碼,可以簡單看下。

    typedef struct quicklistNode {
      struct quicklistNode *prev;
      struct quicklistNode *next;
      unsigned char *zl;
      unsigned int sz;       /* ziplist size in bytes */
      unsigned int count : 16;   /* count of items in ziplist */
      unsigned int encoding : 2;  /* RAW==1 or LZF==2 */
      unsigned int container : 2; /* NONE==1 or ZIPLIST==2 */
      unsigned int recompress : 1; /* was this node previous compressed? */
      unsigned int attempted_compress : 1; /* node can't compress; too small */
      unsigned int extra : 10; /* more bits to steal for future usage */
    } quicklistNode;
    
    typedef struct quicklistLZF {
      unsigned int sz; /* LZF size in bytes*/
      char compressed[];
    } quicklistLZF;
    
    typedef struct quicklist {
      quicklistNode *head;
      quicklistNode *tail;
      unsigned long count; /* total count of all entries in all ziplists */
      unsigned int len; /* number of quicklistNodes */
      int fill : 16; /* fill factor for individual nodes */
      unsigned int compress : 16; /* depth of end nodes not to compress;0=off */
    } quicklist;
    

    quicklist的主要作用就是來指向節點的頭和尾

    總結

    總的來說quicklist就是對ziplist和linkedlist兩者優點的結合,來進一步優化redis的列表鍵底層存儲。

    到此這篇關于Redis快速表、壓縮表和雙向鏈表(重點介紹quicklist)的文章就介紹到這了,更多相關Redis快速表、壓縮表和雙向鏈表內容請搜索真格學網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持真格學網!

    您可能感興趣的文章:詳解Redis用鏈表實現消息隊列redis中hash表內容刪除的方法代碼Redis列表類型的常用命令小結Redis List列表的詳細介紹詳解Redis中的雙鏈表結構redis列表類型_動力節點Java學院整理詳解Redis數據結構之跳躍表Redis數組和鏈表深入詳解

  3. 本文相關:
  4. 詳解redis的慢查詢日志
  5. redis 用scan指令 代替keys指令(詳解)
  6. 詳解用redis實現session功能
  7. 使用redis獲取數據轉json,解決動態泛型傳參的問題
  8. redis基本類型和使用方法詳解
  9. redis配置文件redis.conf詳細配置說明
  10. 使用springboot集成redis的方法
  11. redis3.2.6配置文件詳細中文說明
  12. springsession+redis實現集群會話共享的方法
  13. 淺談我是如何用redis做實時訂閱推送的
  14. 如何用Java和Redis設計一個高效的先入先出的隊列
  15. 詳細介紹redis的幾種數據結構以及使用注意事項
  16. java List集合與redis數據快速比對
  17. redis中有序集合類型和列表類型的不同點與相同點
  18. redis的基本數據結構有哪些,都有什么應用
  19. Redis和Memcache的區別總結
  20. 為啥redis 使用跳表而不是使用 red-black
  21. 使用python同步mysql到redis?由于數據較多,一條一...
  22. 怎么和測試人員介紹redis數據有哪些類型?
  23. redis數據庫有哪些特點?
  24. 網站首頁網頁制作腳本下載服務器操作系統網站運營平面設計媒體動畫電腦基礎硬件教程網絡安全mssqlmysqlmariadboracledb2mssql2008mssql2005sqlitepostgresqlmongodbredisaccess數據庫文摘數據庫其它首頁詳解redis用鏈表實現消息隊列redis中hash表內容刪除的方法代碼redis列表類型的常用命令小結redis list列表的詳細介紹詳解redis中的雙鏈表結構redis列表類型_動力節點java學院整理詳解redis數據結構之跳躍表redis數組和鏈表深入詳解詳解redis的慢查詢日志redis 用scan指令 代替keys指令(詳解)詳解用redis實現session功能使用redis獲取數據轉json,解決動態泛型傳參的問題redis基本類型和使用方法詳解redis配置文件redis.conf詳細配置說明使用springboot集成redis的方法redis3.2.6配置文件詳細中文說明springsession+redis實現集群會話共享的方法淺談我是如何用redis做實時訂閱推送的超強、超詳細redis數據庫入門教程redis常用命令、常見錯誤、配置技redis操作命令總結redis中5種數據結構的使用場景介64位windows下安裝redis教程redis中使用redis-dump導出、導入redis中統計各種數據大小的方法redis 密碼設置和查看密碼的方法redis常用命令小結讓redis在你的系統中發揮更大作用如何利用 redis 實現接口頻次限制redis與mongodb的區別總結redis優化經驗總結(必看篇)redis 在真實世界的 5 個用法redislive監控redis服務的圖文教程_動力節redis如何使用lua腳本實例教程redis事務_動力節點java學院整理一篇文章讓你明白redis主從同步redis的2種持久化方案深入講解redisdesktopmanager無法遠程連接redis的
    免責聲明 - 關于我們 - 聯系我們 - 廣告聯系 - 友情鏈接 - 幫助中心 - 頻道導航
    Copyright © 2017 www.yu113.com All Rights Reserved
    战天txt全集下载