Databases 10 min read

Understanding Redis Ziplist: Structure, Encoding, and Chain Updates

This article explains Redis's ziplist—a compact list implementation used for small integers and short strings—by detailing its memory layout, field meanings, entry encoding schemes, the role of previous_entry, and the chain‑update behavior that occurs when nodes are added or removed.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Understanding Redis Ziplist: Structure, Encoding, and Chain Updates

When a Redis list contains only a few items consisting of small integers or short strings, Redis stores the data using a special compact structure called a ziplist . A ziplist is a contiguous memory block that can be thought of as an array, but it also stores metadata such as total length, tail offset, and the length of the previous entry.

The ziplist header consists of four fields:

Field

Type

Length

Purpose

zlbytes

uint32_t

4 bytes

Total number of bytes occupied by the ziplist.

zltail

uint32_t

4 bytes

Offset of the tail entry from the start of the ziplist.

zllen

uint16_t

2 bytes

Number of entries (max 65,535; larger lists require traversal to count).

entry …

entry

variable

Actual data nodes; length is dynamic.

zlend

uint8_t

1 byte

Fixed value 0xFF marking the end of the ziplist.

Each entry consists of three parts: previous_entry , encoding , and content . The previous_entry field stores the length of the preceding node. It normally uses a single byte, but if the length exceeds 254 bytes, Redis expands it to five bytes: the first byte is set to 0xFE and the following four bytes hold the actual length. This design allows Redis to keep most entries compact while still supporting larger nodes.

Previous Entry

The previous_entry field can occupy up to five bytes. Redis first tries to store the length in one byte; only when the length is greater than 254 does it switch to the five‑byte representation. The special marker 0xFE is used because 0xFF is reserved for the zlend terminator.

Encoding

The encoding byte describes both the data type and the length of the entry's payload. The two most‑significant bits indicate the type:

00 : string with length ≤ 63 bytes (1‑byte encoding).

01 : string with length ≤ 16,383 bytes (2‑byte encoding).

10 : string with length ≤ 4,294,967,295 bytes (5‑byte encoding).

11 : integer (various integer sizes).

After stripping the two type bits, the remaining bits represent the length of the payload. The following table summarizes the possible encodings:

Encoding

Length (bytes)

Value

00aaaaaa

1

String length ≤ 63

01pppppp|qqqqqqqq

2

String length ≤ 16,383

10xxxxxx|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt

5

String length ≤ 4,294,967,295

11000000

1

int16

11010000

1

int32

11100000

1

int64

11110000

1

24‑bit signed integer

11111110

1

8‑bit signed integer

1111xxxx (xxxx = 0000‑1101)

1

Values 0‑12

11111111

1

Ziplist end marker (0xFF)

Example: 00001000

The leading bits are 00 , indicating a short string. The remaining six bits 001000 equal 8 in decimal, so the entry stores a 1‑byte string of length 8.

Example: 01000001,00000000

The leading bits 01 denote a 2‑byte string. The following 14 bits represent the length 256, meaning the entry holds 256 bytes of data (e.g., 32 English characters if each occupies 8 bytes).

Content

The content field stores the actual payload, which can be either a string or an integer as described by the encoding. Because the length is already encoded, the parser does not need to examine the payload to determine the entry size.

When many entries have lengths in the range 250‑254 bytes, adding a new 254‑byte node at the head forces the first entry's previous_entry to expand from 1 to 5 bytes, which in turn shifts the offsets of subsequent entries. This ripple effect is called a chain update . Deleting nodes can trigger a similar cascade.

In summary, ziplist is optimal for storing a small number of short strings or integers, offering memory efficiency through compact headers, variable‑length previous_entry , and concise encodings, while chain updates remain rare due to the limited use case.

memory-optimizationRedisdata structuresdatabasesziplist
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.