Skip to content

Step 1 of 3 · Reading · ~2 min

Redis Lists

Lists

Lists: your first non-scalar type

Every value you've stored so far has been a single string. Redis's list type is where your server starts needing real data structures — an ordered sequence of strings living behind one key, with fast insertion at both ends.

Choosing the underlying structure

A Python list looks tempting, but list.insert(0, x) is O(n) — every push to the front shifts the whole array. Real Redis uses a doubly-linked list (historically) or a quicklist of linked ziplists. In your server, the simplest correct choice is collections.deque, which gives O(1) appendleft and append:

python

The head/tail ordering subtlety

LPUSH mylist a b c doesn't push a, then b, then c onto the head one at a time and leave you with a b c — each push happens in argument order, so the last argument ends up closest to the head:

LPUSH mylist a b c
# step 1: pushLeft(a) -> [a]
# step 2: pushLeft(b) -> [b, a]
# step 3: pushLeft(c) -> [c, b, a]

Final list: c, b, a. This trips people up constantly — write a small trace like the one above before you code it, and test it explicitly.

RPUSH is the mirror image: append each value in order to the tail, so RPUSH mylist a b c yields a, b, c in that natural order.

Type checking and shared storage

Because a Redis key can hold exactly one type at a time, before pushing you must check whether the key already exists as something other than a list (e.g. a string set with SET). If your server keeps separate dicts per type (strings, lists, hashes, ...), checking "does this key exist in a different dict" is enough:

python

If the check fails, reply with the exact wire error:

-WRONGTYPE Operation against a key holding the wrong kind of value\r\n

Note the error starts with - (RESP error prefix) and is terminated with \r\n — not \n. Getting the line ending wrong is a classic bug that only shows up when a strict client parses your reply.

The reply: an integer

Both LPUSH and RPUSH reply with the new length of the list after the push, encoded as a RESP integer: :3\r\n. This lets clients chain pushes and know the resulting size without a separate LLEN call — keep that return value in mind as you wire up your command dispatcher.

Up nextLPOP, RPOP & LLENLists

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…