redisソースコードのデータ構造(5)--ziplist実装

2022 ワード

前回はzipmapのソースコードを分析し、zipmapはredisで鶏の肋骨を比較したが、実際には2.6バージョンではzipmapデータ構造は使用されず、zipmapはziplistで代替することができる.ziplistは文字列でデュアルチェーンテーブルを実現し、メモリを非常に節約し、文字列を格納したり、整数を格納したりすることができます.ziplist両端のpopとpush操作はO(1)時間で完了できる.ただし、ziplistの操作のたびにlistのreallocが必要になる可能性があるため、複雑さはziplistが使用するメモリサイズに関連しています.
ziplistのメモリレイアウト:
 
ziplistが占有する総バイト数を表す.ziplistの最後のentryのオフセット(先頭に対して)を表し、このフィールドに追加し、主にpop操作がO(1)時間以内に完了できるようにします.entryを表すチェーンテーブルノードの数ですが、ノード数が2^16-2より大きい場合は、ループでしかチェーンテーブル長が得られません.は、チェーンテーブルの末尾を示す255に等しいフラグバイトです.
ziplistのノードデータ構造を見てみましょう.
typedef struct zlentry {
    unsigned int prevrawlensize, prevrawlen;
    unsigned int lensize, len;
    unsigned int headersize;
    unsigned char encoding;
    unsigned char *p;
} zlentry;

prevrawlensizeは、前のノードの長さを格納するために必要なバイト数であり、prevrawlenは前のノードの占有バイト数を格納し、後から前へ巡回することができる(双方向チェーンテーブル).
lensizeは、現在のノードの長さを格納するために必要なバイト数であり、lenは現在のノードが占有するバイト数である.
headersize現在のノードヘッダサイズ
Encodingは、現在のノードのlenフィールドの符号化タイプを表します.
pは、現在のノードの開始位置を指す.
ziplistノードストレージ構造
この数値により,前方を遍歴し,双方向チェーンテーブルを実現できる.前のノードが254未満の場合、1バイトで表され、そうでない場合、前のノードの長さは5バイトで表され、最初のバイトの数値は254であり、残りの4バイトは前のノードの真の長さを表す.
最初のバイトの最初の2桁はデータ型を表します.具体的なコードは以下の通りです.
  |00pppppp| - 1 byte
              ,        63  
  |01pppppp|qqqqqqqq| - 2 bytes
             ,       16383 bytes (14 bits).
  |10______|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| - 5 bytes
              ,     16384。
  |11000000| - 1 byte
           ,     2        int16_t (2 bytes).
  |11010000| - 1 byte
           ,     4         encoded as int32_t (4 bytes).
  |11100000| - 1 byte
           ,     8        encoded as int64_t (8 bytes).
  |11110000| - 1 byte
           ,     3        encoded as 24 bit signed (3 bytes).
  |11111110| - 1 byte
           ,     2        encoded as 8 bit signed (1 byte).
  |1111xxxx| - (with xxxx between 0000 and 1101) immediate 4 bit integer.
       Unsigned integer from 0 to 12.     , 13      ,             1~13,     1,       。
  |11111111| -