Skip to content

Redis Data Structures: An Overview

Aman Kumar Singh4 min read
Part 2 of 15From the Redis Masterclass series
Redis Data Structures: An Overview — article by Aman Kumar Singh

The reason Redis solves so many problems is that it isn't one thing, it's a collection of data structures, each with commands tuned for a specific access pattern. Picking the right structure for a problem is most of using Redis well, because the right one makes an operation atomic and instant, while the wrong one turns it into a slow read-modify-write dance in your application. This article is the map: what each core structure is, and the kind of problem it's shaped for. The next several articles go deep on each.

This is part 2 of the Redis Masterclass, following what Redis is.

Strings: the simplest value

A Redis string is a value up to 512MB, holding text, a number, JSON, or binary data. Despite the name, strings are also how you store counters, because Redis has atomic increment commands:

SET user:1:name "Aman"
INCR page:home:views        # atomic counter, no read-modify-write
SETEX session:abc 3600 "..."  # set with a 1-hour expiry

Strings are the workhorse for cached values (store a serialized object under a key) and for counters (views, rate-limit counts, likes). The atomic INCR is the key feature: many clients can increment the same counter with no race condition, which you'd struggle to do correctly against a plain database column.

Hashes: objects with fields

A hash stores field-value pairs under a single key, like an object or a row:

HSET user:1 name "Aman" plan "pro" logins 42
HGET user:1 plan            # read one field
HINCRBY user:1 logins 1     # atomically bump one field

Hashes are ideal for storing an object you'll read and update field by field, without serializing and deserializing the whole thing each time. A user session, a cached record, a config object: a hash lets you update logins without touching name, which is both efficient and avoids clobbering concurrent changes to other fields.

Lists: ordered sequences and queues

A list is an ordered collection you push and pop from either end:

LPUSH queue:emails "job1"    # add to the left
RPOP queue:emails            # remove from the right (FIFO with LPUSH)
LRANGE timeline:1 0 9        # get the first 10 items

Lists back simple queues (push on one end, pop on the other) and recent-items feeds (a capped list of the latest activity). With blocking commands like BRPOP, a list becomes a simple work queue where consumers wait for jobs. For richer queuing, streams (later in the series) are usually better, but lists are the quick answer for straightforward FIFO or LIFO needs.

Sets: unique collections

A set is an unordered collection of unique values, with fast membership tests and set algebra:

SADD article:1:tags "redis" "database"
SISMEMBER article:1:tags "redis"   # is it a member? O(1)
SINTER user:1:follows user:2:follows  # mutual follows

Sets shine for "is X in this group" checks (a user's permissions, IPs seen, tags) and for set operations like intersection and union computed in the database. Finding mutual friends, common tags, or unique visitors is a set intersection or a set cardinality, done atomically in Redis instead of in application code.

Sorted sets: ranked data

A sorted set (zset) is a set where every member has a score, and members are kept ordered by that score. This is the most powerful Redis structure and the one people underuse:

ZADD leaderboard 1500 "player1" 1800 "player2"
ZREVRANGE leaderboard 0 9 WITHSCORES   # top 10 by score
ZRANK leaderboard "player1"            # a member's rank

Sorted sets are the answer for anything ranked or ordered by a value: leaderboards (score is points), priority queues (score is priority), time-ordered data (score is a timestamp), and rate limiting with sliding windows (score is time). Getting the top N, a member's rank, or a range by score are all fast, built-in operations. A surprising number of "how do I do X in Redis" questions have "use a sorted set" as the answer.

The specialized structures

Beyond the core five, Redis has structures for specific jobs, which later articles cover:

  • Streams: an append-only log for event processing and durable queues with consumer groups.
  • Bitmaps: bit-level operations on strings, for compact flags like daily-active-user tracking.
  • HyperLogLog: approximate unique counts (cardinality) in tiny fixed memory.
  • Geospatial: storing coordinates and querying by distance, built on sorted sets.
  • Bloom filters (via a module): probabilistic membership tests using minimal memory.

Choosing the right one

The skill is matching the problem to the structure:

  • A single value or counter: string.
  • An object with fields you update independently: hash.
  • A FIFO/LIFO queue or recent-items list: list.
  • Unique membership or set math: set.
  • Anything ranked, scored, or ordered by a value: sorted set.
  • An event log or durable queue with consumers: stream.

Get this choice right and Redis operations are atomic one-liners. Get it wrong (say, faking a leaderboard by reading a list into your app and sorting it) and you lose both the speed and the atomicity that make Redis worth using. When a Redis task feels awkward, the usual cause is the wrong structure, and the fix is picking the one the problem actually fits.

Next, we start with strings in detail: values, atomic counters, and the operations that make them more than simple storage.

Key takeaways

  • Redis provides several data structures, each with commands tuned to a specific access pattern; choosing the right one is most of using it well.
  • Strings hold values and atomic counters; hashes hold objects with independently-updatable fields.
  • Lists are ordered sequences for queues and feeds; sets are unique collections with fast membership and set algebra.
  • Sorted sets rank members by a score and answer leaderboards, priority queues, and time-ordered queries efficiently.
  • Specialized structures (streams, bitmaps, HyperLogLog, geospatial, bloom filters) handle event logs, compact flags, and approximate counts.

Frequently asked questions

What data structures does Redis support?

The core ones are strings, hashes, lists, sets, and sorted sets. Redis also has streams, bitmaps, HyperLogLog, geospatial indexes, and (via a module) bloom filters, each suited to a specific kind of problem.

When should I use a hash instead of a string?

Use a hash when you're storing an object with multiple fields you read or update independently, like a user record. A hash lets you update one field without rewriting the whole value, unlike serializing an object into a single string.

What is a sorted set used for?

Anything ranked or ordered by a value: leaderboards (score is points), priority queues (score is priority), time-ordered data (score is a timestamp), and sliding-window rate limiting. It efficiently returns the top N, a member's rank, or a range by score.

How do I choose the right Redis data structure?

Match it to the access pattern: strings for values and counters, hashes for objects, lists for queues, sets for unique membership and set math, and sorted sets for ranked data. The right structure makes the operation atomic and fast.

What's the difference between a set and a list in Redis?

A list is ordered and allows duplicates, suited to queues and sequences. A set is unordered, stores only unique values, and offers fast membership tests and set operations like intersection and union.

Related articles

Redis Caching Best Practices and Pitfalls — Aman Kumar Singh
Cache Invalidation Strategies with Redis — Aman Kumar Singh
Refresh-Ahead Caching with Redis — Aman Kumar Singh
Aman Kumar Singh

About the author

I'm Aman Kumar Singh, a software engineer in Noida, India building scalable full-stack products with React, Next.js, Node.js, NestJS, PostgreSQL, Redis, and AWS. I write about backend engineering, distributed systems, and system design.