基于Redis 6.0

压缩列表中单个元素结构ziplistEntry

// src/ziplist.h

/* Each entry in the ziplist is either a string or an integer. */
typedef struct {
    /* When string is used, it is provided with the length (slen). */
    unsigned char *sval;
    unsigned int slen;
    /* When integer is used, 'sval' is NULL, and lval holds the value. */
    long long lval;
} ziplistEntry;

整个压缩列表结构为:

  1. 列表头zlbytes,4字节表示压缩列表字节长度,包括自己。
  2. 列表头zltail,4字节标识最后一个entry的偏移量。
  3. 列表头zllen,2字节标识entry数量。超过2^16-2的情况下会记为2^16-1并且失效,进而获取数量需要通过遍历获取。
  4. entry,实际元素。
  5. 列表尾zlend,1字节=255,标识列表结束。
<zlbytes> <zltail> <zllen> <entry> <entry> ... <entry> <zlend>

单个entry的结构为:

  1. prevlen。上一个entry的长度。如果上一个entry长度小于254bytes,则用一个字节表示。如果大于等于254bytes,则用5个字节,第一个字节设置254作为标识位,下4个字节表示长度。
  2. encoding,表示当前entry的编码。encoding逻辑比较复杂见下文。
<prevlen> <encoding> <entry-data>

Or alternatively if the previous entry length is greater than 253 bytes the following encoding is used:

0xFE <4 bytes unsigned little endian prevlen> <encoding> <entry>

特殊情况下,如int类型比较小,encoding直接表示为data本身,则entry-data为null。

<prevlen> <encoding>

encoding编码逻辑:

 * |00pppppp| - 1 byte
 *      String value with length less than or equal to 63 bytes (6 bits).
 *      "pppppp" represents the unsigned 6 bit length.
 * |01pppppp|qqqqqqqq| - 2 bytes
 *      String value with length less than or equal to 16383 bytes (14 bits).
 *      IMPORTANT: The 14 bit number is stored in big endian.
 * |10000000|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| - 5 bytes
 *      String value with length greater than or equal to 16384 bytes.
 *      Only the 4 bytes following the first byte represents the length
 *      up to 2^32-1. The 6 lower bits of the first byte are not used and
 *      are set to zero.
 *      IMPORTANT: The 32 bit number is stored in big endian.
 * |11000000| - 3 bytes
 *      Integer encoded as int16_t (2 bytes).
 * |11010000| - 5 bytes
 *      Integer encoded as int32_t (4 bytes).
 * |11100000| - 9 bytes
 *      Integer encoded as int64_t (8 bytes).
 * |11110000| - 4 bytes
 *      Integer encoded as 24 bit signed (3 bytes).
 * |11111110| - 2 bytes
 *      Integer encoded as 8 bit signed (1 byte).
 * |1111xxxx| - (with xxxx between 0001 and 1101) immediate 4 bit integer.
 *      Unsigned integer from 0 to 12. The encoded value is actually from
 *      1 to 13 because 0000 and 1111 can not be used, so 1 should be
 *      subtracted from the encoded 4 bit value to obtain the right value.
 * |11111111| - End of ziplist special entry.