Redis Data Structures

Redis is often described as a key-value store, but the values are what make it powerful. Each key holds a typed data structure: a string, hash, list, set, sorted set, stream, and more. Each type comes with atomic server-side commands. Instead of fetching a blob, modifying it in your app, and writing it back, you tell Redis "increment this counter", "add this member with score 42", or "pop the next job". The operation runs atomically in memory in microseconds.

Choosing the right structure is most of Redis design. A leaderboard is a sorted set, a rate limiter is a string counter with a TTL, a job queue is a list or a stream, and a session is a hash. This page maps each type to its commands, costs, and typical uses.

TL;DR

Quick Example

A leaderboard, a session, and a recent-activity feed:

Each command is atomic. Two clients calling ZINCRBY at once can't lose an update.

Core Concepts

Strings

The most basic type, binary-safe and holding text, serialized JSON, integers, or raw bytes.

Hashes

A map of fields to values under one key, ideal for objects:

Small hashes are stored in a compact encoding (listpack), so many small hashes are very memory-efficient. Redis 7.4+ also supports per-field expiration (HEXPIRE).

Lists

Linked sequences with O(1) pushes and pops at both ends. LPUSH + BRPOP makes a simple blocking queue; LMOVE moves an item to a processing list for at-least-once handling. Index access (LINDEX, LRANGE deep into the list) is O(n), so lists suit head and tail operations, not random access.

Sets

Unordered collections of unique strings with O(1) add, remove, and membership:

SINTER, SUNION, and SDIFF compute set algebra server-side. SRANDMEMBER and SPOP pick random members.

Sorted Sets

Each unique member has a floating-point score, and members stay ordered by it. Range and rank queries are O(log n + m). This is the most versatile Redis type:

Streams

An append-only log of entries with auto-generated time-based IDs. Consumer groups let multiple workers share a stream with acknowledgements, pending-entry tracking, and redelivery, a lightweight Kafka-like model inside Redis. Details in Redis Pub/Sub & Streams.

Specialized Types

Keys and Expiration

Best Practices

Pick the Structure That Matches the Query

Design from access patterns. If you need "top N by score", use a sorted set, not a serialized list you sort in the app. If you update single fields, use a hash, not a JSON string you rewrite whole.

Avoid Big Keys

A single hash, list, or set with millions of elements makes commands like HGETALL, DEL, or SMEMBERS block the single-threaded command loop and complicates cluster balancing. Shard large collections across keys (followers:42:0…followers:42:15), paginate with HSCAN/SSCAN/ZSCAN, and delete with UNLINK (asynchronous).

Set TTLs on Cache and Ephemeral Data

Anything that isn't a source of truth should expire. Keys without TTLs accumulate until memory fills and the eviction policy starts removing data you care about.

Pipeline Round Trips

Latency is usually network-bound. Send batches of commands with pipelining, or use variadic commands (MGET, HSET with many fields, ZADD with many members), to cut round trips dramatically.

Common Mistakes

Storing Objects as JSON Strings, Then Rewriting Them

Using KEYS in Production

KEYS pattern scans every key in one blocking call and can freeze a large instance for seconds. Use SCAN cursors, or maintain explicit index sets.

Using Lists as Reliable Queues Without Acknowledgement

RPOP removes a job immediately. If the worker crashes, the job is lost. Use LMOVE into a processing list, or Streams with consumer groups, which track unacknowledged messages.

FAQ

Which Redis data type should I use for caching?

Usually strings holding serialized values with a TTL. Use hashes when you frequently read or update individual fields of a cached object. See Redis caching patterns for strategies like cache-aside and stampede protection.

How much memory does Redis use per key?

Roughly 50–100 bytes of overhead per key, plus the value. Small hashes, sets, and sorted sets use compact encodings, so grouping many small values into hashes can dramatically reduce memory. MEMORY USAGE key reports the real size of a key.

Are Redis operations atomic?

Each individual command is atomic: Redis executes commands one at a time on its main thread. For multi-command atomicity use MULTI/EXEC (optionally with WATCH for optimistic locking) or a Lua script/Function, which runs without interleaving.

What's the difference between a set and a sorted set?

Both hold unique members. A set is unordered, with O(1) membership checks and set algebra. A sorted set attaches a score to each member and keeps them ordered, enabling rank and range queries at O(log n) cost per operation.

Related Topics

References