English | 中文版
[TOC]
Ziplist is one of the compact encodings Redis uses for list and hash objects. When a list contains few elements and each element is either a small integer or a short string, Redis uses ziplist as the underlying representation.
Example: the following commands produce a list stored as a ziplist:
redis> RPUSH lst 1 3 5 10086 "hello" "world"
redis> OBJECT ENCODING lstA ziplist is laid out as:
|zlbytes|zltail|zllen|entry1|entry2|...|entryN|zlend|
| field | type | length (bytes) | description |
|---|---|---|---|
| zlbytes | uint32_t | 4 | total number of bytes used by the ziplist (used when reallocating or finding zlend) |
| zltail | uint32_t | 4 | offset to the last entry from the start of the ziplist (allows locating tail without traversal) |
| zllen | uint16_t | 2 | number of entries when < UINT16_MAX; if equal to UINT16_MAX the real length must be computed by traversal |
| entryX | element | variable | entries; each entry length depends on its content |
| zlend | uint8_t | 1 | termination byte 0xFF |
Example (three entries):
| zlbytes | zltail | zllen | entry1 | entry2 | entry3 | zlend |
|---|---|---|---|---|---|---|
| 0x50 | 0x3c | 0x3 | 0xFF |
zlbytes = 0x50 (80)total byteszltail = 0x3c (60)offset from start to entry3zllen = 0x3 (3)number of entries
Each entry consists of three parts:
| previous_entry_length | encoding | content |
|---|---|---|
| 1~5 bytes | variable | variable |
-
previous_entry_lengthrecords the length (in bytes) of the previous entry:- If the previous entry length < 254, this field is 1 byte.
- If the previous entry length >= 254, this field is 5 bytes: first byte = 0xFE, next 4 bytes store the length.
-
encodingdescribes the type and length ofcontent.
String encodings:
| encoding pattern | header length | content |
|---|---|---|
00bbbbbb |
1 | string up to 63 bytes |
01bbbbbb xxxxxxxx |
2 | string up to 16383 bytes |
10_____ aaaaaaaa bbbbbbbb cccccccc dddddddd |
5 | string up to 4294967295 bytes |
Integer encodings:
| encoding | length (bytes) | content |
|---|---|---|
11000000 |
1 | int16_t |
11010000 |
1 | int32_t |
11100000 |
1 | int64_t |
11110000 |
1 | 24-bit signed integer |
11111110 |
1 | 8-bit signed integer |
1111xxxx |
1 | immediate integer encoded in the lower 4 bits (value 0..12) — no content bytes |
contentholds either the byte array or integer value as indicated byencoding.
Example: an entry storing the string "hello world":
| previous_entry_length | encoding | content |
|---|---|---|
| ... | 00001011 | "hello world" |
If multiple consecutive entries have previous_entry_length encoded as 1 byte (previous entry < 254 bytes), inserting a new entry whose size is >= 254 will require the subsequent entries' previous_entry_length fields to expand from 1 to 5 bytes. This can trigger a chain of reallocations and updates called a "cascade update".
Both insertions and deletions can trigger cascade updates.
Worst-case complexity: a cascade update may perform up to N reallocations, each costing up to
| Function | Purpose | Complexity |
|---|---|---|
ziplistNew |
Create a new empty ziplist | |
ziplistPush |
Create a new entry with the given value and push to head or tail | average |
ziplistInsert |
Insert a new entry after a given entry | average |
ziplistIndex |
Return entry at a given index | |
ziplistFind |
Find an entry containing the given value | value compare is |
ziplistNext |
Return the next entry of a given entry | |
ziplistPrev |
Return the previous entry of a given entry | |
ziplistGet |
Extract the value stored in an entry | |
ziplistDelete |
Delete a given entry from the ziplist | average |
ziplistDeleteRange |
Delete a range of consecutive entries | average |
ziplistBlobLen |
Return total size in bytes of the ziplist | |
ziplistLen |
Return number of entries (if < 65535 |
- |
Note: ziplistPush, ziplistInsert, ziplistDelete, and ziplistDeleteRange may trigger cascade updates.
[1] Huang Jianhong. Redis Design and Implementation