Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← MongoDB & NoSQL Design

NoSQL Fundamentals

  • SQL vs NoSQL Trade-offs
  • Wide-Column Modeling with Cassandra
  • DynamoDB Key Design & Single-Table Modeling
  • Redis Data Structures & Use Cases
Chaturmind
← MongoDB & NoSQL Design

NoSQL Fundamentals

  • SQL vs NoSQL Trade-offs
  • Wide-Column Modeling with Cassandra
  • DynamoDB Key Design & Single-Table Modeling
  • Redis Data Structures & Use Cases
HomeLearnDatabasesMongoDB & NoSQL DesignNoSQL Fundamentals
✓ FreeIntermediate· 6 min read

Redis Data Structures & Use Cases

Strings, hashes, lists, sets, sorted sets and streams — and the features each one makes trivial.

Published September 24, 2026


Redis Data Structures & Use Cases

Redis is often introduced as "a cache", but its real strength is that it's an in-memory data structure server. Instead of storing opaque values, it offers strings, hashes, lists, sets, sorted sets, streams and more, each with atomic operations that run in microseconds. Choosing the right structure turns many backend features (leaderboards, rate limiting, deduplication, job queues) into one or two commands.

Everything lives in RAM, and commands execute one at a time on a single main thread. That design explains both its speed (no locking, no disk seeks on the request path) and its main constraints (dataset size is bounded by memory, and one slow command blocks everyone).

Strings: counters, flags and simple caching

A string holds up to 512 MB: text, serialized JSON, or a number.

SET session:9f2c "{...}" EX 1800        # value with a 30-minute expiry
INCR page:views:home                    # atomic counter: no read-modify-write race
SET lock:report "worker-7" NX PX 30000  # set only if absent, auto-expires: a simple lock

INCR, and SET … NX, are atomic, which removes whole classes of race conditions that would need transactions elsewhere. Always set expirations on cache-like keys. A Redis instance without TTLs slowly fills up.

Hashes: small objects

A hash maps field names to values under one key, like a lightweight row:

HSET user:42 name "Asha" plan "pro" logins 17
HINCRBY user:42 logins 1
HGET user:42 plan

Hashes let you read or update individual fields without rewriting a serialized blob, and small hashes are stored very compactly.

Lists: queues and recent items

Lists are ordered, and support O(1) pushes and pops at both ends:

LPUSH recent:user:42 "product:981"      # newest first
LTRIM recent:user:42 0 19               # keep only the last 20 viewed items
LRANGE recent:user:42 0 9               # show 10
BRPOP jobs 5                            # blocking pop: a simple work queue

LPUSH combined with LTRIM is the idiomatic "last N items" pattern. Lists work as basic queues, but a popped job is lost if the worker crashes before finishing it. For reliable processing, use Streams (below).

Sets: uniqueness and membership

SADD online:users 42 77 105
SISMEMBER online:users 42               # O(1) membership test
SINTER tags:java tags:spring            # items tagged with both

Sets are good for de-duplication, tagging, and "who's online" style features. For counting distinct items at huge scale (unique visitors per day), HyperLogLog (PFADD/PFCOUNT) estimates cardinality within about 1% error, using only around 12 KB per counter, instead of storing every ID.

Sorted sets: leaderboards, rankings and time windows

A sorted set keeps unique members ordered by a numeric score, with O(log n) updates and range queries:

ZINCRBY leaderboard:weekly 50 "player:42"          # add points
ZREVRANGE leaderboard:weekly 0 9 WITHSCORES         # top 10
ZREVRANK leaderboard:weekly "player:42"             # this player's position

Using timestamps as scores turns sorted sets into time-ordered indexes. That's the basis of a precise sliding-window rate limiter:

ZREMRANGEBYSCORE ratelimit:user:42 0 (now - 60000)   # drop requests older than 60 s
ZADD ratelimit:user:42 now requestId                 # record this request
ZCARD ratelimit:user:42                              # how many in the window?
EXPIRE ratelimit:user:42 60

Wrap these in a Lua script (or a MULTI/EXEC transaction), so the check and the insert happen atomically. Redis runs Lua scripts without interleaving other commands.

Streams: durable, consumer-group messaging

Streams are an append-only log with consumer groups, similar in spirit to Kafka topics, built into Redis:

XADD orders * orderId 981 total 129.49             # append an event
XGROUP CREATE orders billing $ MKSTREAM            # a consumer group
XREADGROUP GROUP billing worker-1 COUNT 10 STREAMS orders >
XACK orders billing 1712345678901-0               # confirm processing

Messages delivered to a consumer stay pending until acknowledged. If a worker crashes, another can claim its pending messages (XAUTOCLAIM). That gives at-least-once processing, which plain lists can't. It's good for moderate-volume event processing and job queues when you already run Redis.

Persistence and durability

In-memory doesn't have to mean volatile, but you must choose a durability setting:

  • RDB snapshots: periodic point-in-time dumps. Compact, and fast to restart from, but you lose writes made since the last snapshot.
  • AOF (append-only file): logs every write. With appendfsync everysec, you lose at most about one second of writes on a crash.
  • Both together are common for data you care about. For a pure cache, persistence can be off entirely.

Replication (a primary with replicas, plus Sentinel or a managed service for automatic failover) protects availability. Replication is asynchronous, though, so a failover can lose the last few acknowledged writes. Don't use Redis as the only system of record for money or other critical state.

Scaling and operational pitfalls

  • Memory is the limit. Set maxmemory, and choose an eviction policy: allkeys-lru or allkeys-lfu for caches, noeviction for data that must never silently disappear.
  • Big keys: a list or hash with millions of elements makes commands on it slow, and blocks the single thread. Split large collections into buckets.
  • Slow commands: KEYS *, SMEMBERS on huge sets, and unbounded LRANGEs block every other client. Use SCAN-family commands for iteration, and bound all range reads.
  • Redis Cluster shards keys across nodes, in 16,384 hash slots. Multi-key operations work only when the keys are in the same slot. Force related keys together with hash tags: {user:42}:cart and {user:42}:profile land in the same slot.

Follow-up questions this topic invites — and their answers

Q: Why is Redis so fast? A: Data lives in memory, commands run on a single thread without lock contention, the data structures are highly optimized, and network I/O is handled efficiently. Most operations complete in microseconds, so the network round trip usually dominates.

Q: How would you build a leaderboard with Redis? A: Use a sorted set, with players as members and scores as points. ZINCRBY updates scores atomically, ZREVRANGE returns the top N, and ZREVRANK gives a player's position, each in O(log n) time. Use separate keys per period (daily or weekly), with expiry.

Q: When should you use Streams instead of Lists for a queue? A: When you can't afford to lose jobs. Streams keep delivered messages pending until they're acknowledged, support consumer groups, and let other workers claim messages from crashed consumers. Lists remove an item on pop, so a crash mid-processing loses it.

Q: Can Redis be your primary database? A: For some workloads, yes: sessions, leaderboards, counters, or ephemeral state, especially with AOF persistence and replication. For critical records that need strong durability guarantees and complex queries, keep a primary database, and use Redis alongside it. Asynchronous replication and memory limits make it a risky sole system of record.

Q: What are hash tags in Redis Cluster? A: A section of the key in braces, such as {user:42}. Only that part is hashed to choose the slot, so keys sharing a hash tag land on the same node. That makes multi-key operations and Lua scripts across those keys possible in a cluster.

Previous

DynamoDB Key Design & Single-Table Modeling

AI Tutor

Lesson: Redis Data Structures & Use Cases

Quick actions

AI responses can be inaccurate. Verify critical information.