Learn the theory
Redis Commands & Data Structures: how it works
4 min read · Updated
Redis is an in-memory data store that is much more than a key-value cache: every key can hold one of several data structures — strings, lists, hashes, sets, sorted sets — and Redis gives you atomic commands for each. Because the data lives in RAM and commands execute one at a time, operations take microseconds and counters, queues, leaderboards and locks become one-liners. Picking the right structure is most of the skill.
In short
- Redis stores keys that point to values of a specific type; commands are type-specific (
LPUSHworks on lists, not strings). - Most commands are O(1) or O(log N), but a few (
KEYS,SMEMBERS,HGETALLon huge values) are O(N) and can block the server. - Commands run one at a time, so
INCRis atomic — no lost updates between clients. - Keys can have a TTL; expired keys disappear automatically. That makes Redis ideal for caches, sessions and rate limits.
- Use strings for values/counters, lists for queues, hashes for objects, sets for unique collections, sorted sets for rankings.
The data model
Redis is a dictionary: key → value. Keys are binary-safe strings (convention: object:id:field, like user:42:name). The value's type decides which commands apply. Everything lives in memory, with optional persistence to disk (RDB snapshots and the AOF log).
Strings (and counters)
The simplest type: a byte string up to 512 MB. Store cached JSON, tokens, or numbers. INCR/INCRBY/DECR treat the value as an integer and change it atomically — perfect for counters.
SET user:1:name "Ada"
GET user:1:name # "Ada"
INCR visits # (integer) 1 <- atomic
SET lock:job "worker-A" NX EX 20 # only if absent, expires in 20 sLists
An ordered sequence you can push to and pop from both ends in O(1). RPUSH + LPOP gives a FIFO queue; LPUSH + LPOP gives a stack. LRANGE reads a slice (O(N) in the slice size).
RPUSH jobs "email:1" "email:2"
LPOP jobs # "email:1" (first in, first out)
LRANGE jobs 0 -1 # everything leftHashes
A map of field → value stored under one key: a compact way to represent an object (a user, a session) and to read or update single fields without rewriting the whole thing.
HSET user:7 name "Ravi" age 31 city "Pune"
HGET user:7 name
HGETALL user:7Sets
An unordered collection of unique strings with O(1) add, remove and membership tests, plus set algebra: SINTER (in all sets), SUNION (in any), SDIFF. Great for tags, “who liked this”, unique visitors and mutual friends.
SADD friends:ann bob cara dan
SADD friends:bo cara dan eve
SINTER friends:ann friends:bo # cara, danSorted sets
Like a set, but every member has a numeric score and the set is always ordered by it (internally a skip list, so inserts and rank lookups are O(log N)). This is the structure behind leaderboards, priority queues, time-ordered feeds and rate-limit windows.
ZADD scores 120 "ann" 90 "bob" 150 "cara"
ZINCRBY scores 70 "bob" # bob is now 160
ZREVRANGE scores 0 2 WITHSCORES # top 3TTL and expiry
EXPIRE key seconds (or SET … EX) gives a key a time to live. Redis removes expired keys lazily when you access them and actively in the background, so they never accumulate forever. TTL reports remaining seconds (-1 = no expiry, -2 = no such key).
Patterns you can build in a few commands
| Pattern | Recipe |
|---|---|
| Counter / page views | INCR page:home:views |
| Rate limiter | INCR rate:ip then EXPIRE rate:ip 60 on the first hit; reject when the value passes the limit |
| Distributed lock | SET lock:x <token> NX EX 30; release by deleting only if the token matches |
| Job queue | RPUSH queue job to enqueue, LPOP (or blocking BLPOP) to consume |
| Leaderboard | ZADD/ZINCRBY to score, ZREVRANGE … WITHSCORES for the top N |
| Session store | A hash or string per session with a TTL |
Frequently asked questions
- What data structures does Redis support?
- Strings, lists, hashes, sets and sorted sets are the core types. Redis also offers streams, bitmaps, HyperLogLog, geospatial indexes and more, built on top of the same key → value model.
- Why is Redis so fast?
- Data lives in memory, the data structures are simple and efficient, and commands run on a single thread without locking. Network round trips, not computation, usually dominate latency.
- Is Redis single-threaded?
- Command execution happens on one main thread, which makes every command atomic. Newer versions use extra threads for network I/O and background work, but commands still run one at a time.
- How does Redis expire keys?
- When a key has a TTL, Redis deletes it lazily the next time it is accessed and also runs a background process that samples keys and removes expired ones.
- Why shouldn't I use the KEYS command in production?
- KEYS scans the whole keyspace in a single O(N) operation and blocks all other clients while it runs. Use SCAN, which iterates incrementally.
- How do I implement a leaderboard in Redis?
- Use a sorted set: ZADD (or ZINCRBY) to set scores, ZREVRANGE with WITHSCORES for the top N and ZREVRANK to get a player's position — all O(log N).