Redis cookbook - (2)Data Type
Kexin Tang

Redis Data Types

When most developers first encounter Redis, they treat it like a fast key-value store — storing simple strings and calling it a day.

But Redis is much more than that. It offers specialized data structures that not only improve performance but also dramatically simplify backend logic.

In this post, we’ll break down all major Redis data types in a way that’s practical, use-case driven, and easy to recall in interviews or real-world design.

String

Even though it’s called a string, Redis internally stores it as Simple Dynamic String (SDS) — not a basic C-style null-terminated string. That means:

  • Redis knows the length of the string (no scanning required)
  • It preallocates extra space, reducing reallocation
1
2
3
buffer => ['R', 'e', 'd', 'i', 's', '\0', '', '']
len => 5
free => 3

Use Case

Scenario Why String Works Well
Counter / Rate Limiter Atomic INCR, no race conditions
Distributed Lock SET NX → lock if key doesn’t exist
Session Storage Store session in shared Redis rather than storing it in every servers

Hash

Need to store an object? You have three choices:

1
2
3
4
5
6
7
8
9
# Option1: use string to represent attributes
SET user:1:name tom
SET user:1:age 18

# Option2: store serialized object
SET user:1 "{name: tom, age: 18}"

# Option3: store object
HMSET user:1 name tom age 18

Internally, small hashes use ZipList for memory efficiency. As they grow, Redis converts them to HashTable automatically.

List

A Redis List is basically a Linked List with push/pop on both ends.

Internally, small list use ZipList. As they grow, Redis converts them to Double Linked List automatically. For latest version, Redis uses QucikList to implement List type.

Perfect for implementing a basic message queue:

Operation Command Meaning
Push task LPUSH myqueue task1 Insert from left
Pop task RPOP myqueue Remove from right
Blocking pop BRPOP Wait until available

⚠️ But be careful — Lists don’t support multiple consumers consuming the same message. If you need fan-out or acknowledgements, use Stream instead.

Set

Ensures all elements are unique, just like set in Python.

Sorted Set (ZSet)

Just like a Set, but each value has a score. Its implementation is ZipList or SkipList.

Bitmap

Bitmaps are just strings, but interpreted as bits.

1
2
SETBIT login:2025-10-02 123 1	# User 123 logged in today
BITCOUNT login:2025-10-02 # How many logged-in users

Bitmap is super memory-efficient — tracking millions of users in just megabytes. So it’s widely used to track daily login status or collect statistic information.

HyperLogLog

If you only need counts, not actual data — use HyperLogLog.

HyperLogLog is used for cardinality estimation.

  • ✅ Space-efficient → regardless of how many elements are inserted, it uses a fixed and small amount of memory
  • ❌ Probabilistic → results are approximate and only count unique items; actual values cannot be retrieved

Cardinality: For nums = [1, 2, 3, 4, 2, 3, 1, 5], the cardinality is (1, 2, 3, 4, 5).

Use Cases

To count unique visitors to a webpage, simply feed all user IDs into HLL. Minor inaccuracies are acceptable when dealing with large-scale data (e.g. millions of visits).

Stream

Streams were designed to replace Pub/Sub and List-based queues.

Limitations of Redis Pub/Sub:

  • No RDB or AOF persistence → messages are lost after crash
  • No ACK mechanism → messages may be lost mid-transfer
  • Messages are dropped when backlog grows too large

To address these issues, Streams offer:

  • Ordered messages like Lists
  • Automatically generated global IDs for messages
  • Support for consumer groups
  • ACK mechanism → unacknowledged messages are kept in PEL (Pending Entries List) for retry
Feature List Pub/Sub Stream
Persistence ✅ via AOF
Multiple Consumers ✅ (via Consumer Groups)
Acknowledgement

image

Multiple consumer groups can consume the same message. Within a group, however, each message is delivered to only one consumer; once consumed, the group’s cursor advances.

Stream vs Other Message Queues

Compared to disk-based systems like Kafka, Redis Streams have drawbacks:

  • Message loss risk → Redis is memory-based, and persistence may still lose data during flush
  • Message accumulation → Redis is not designed for infinite queues; once limits are hit, old messages are evicted