Redis Data Types & Use Cases
Redis is not just a key-value store; it offers strings, hashes, lists, sets, sorted sets, and more. Choosing the right type reduces memory and simplifies code. This article summarizes the main types, their commands, and typical use cases with examples and a reference table.
Overview
- String: Simplest type; value is a string (or binary). Use for cache objects (JSON blob), counters (INCR), flags, or small blobs. TTL applies to the whole key.
- Hash: A key maps to a map of field-value pairs. Use for one object with multiple attributes (e.g. user profile: name, email, age) when you need to read or update single fields. One TTL per key.
- List: Ordered sequence; push/pop from both ends. Use for queues (LPUSH/RPOP), feeds, or recent-N lists (LTRIM). No per-element TTL.
- Set: Unordered, unique strings. Use for membership (e.g. tags, followers), uniqueness, or set operations (SINTER, SUNION).
- Sorted Set (ZSet): Set with a score for ordering. Use for rankings, leaderboards, time-series (score = timestamp), or priority queues. Range by score or rank (ZRANGE, ZRANGEBYSCORE).
Example
Example 1: String — cache and counter
RedisSET user:1001 "{\"name\":\"Alice\",\"email\":\"a@b.com\"}" EX 3600 GET user:1001 INCR rate:api:1001 INCRBY rate:api:1001 5 GET rate:api:1001
- String is good for a whole cached object or a single counter. TTL with
EX(seconds) orPX(milliseconds).
Example 2: Hash — object with fields
RedisHSET user:1001 name "Alice" email "a@b.com" age 30 HGET user:1001 name HGETALL user:1001 HINCRBY user:1001 age 1 EXPIRE user:1001 3600
- Hash lets you read or update one field without serializing the whole object. One key, one TTL; no TTL per field.
Example 3: Sorted set — leaderboard
RedisZADD leaderboard 1000 "user:1" 800 "user:2" 1200 "user:3" ZREVRANGE leaderboard 0 9 WITHSCORES ZRANK leaderboard "user:2" ZINCRBY leaderboard 50 "user:2"
- ZSet is ideal for rankings: add/update by score, get top-N by rank, or range by score (e.g. time window).
Example 4: List — simple queue
RedisLPUSH task:queue '{"id":1,"payload":"..."}' RPOP task:queue -- or blocking: BRPOP task:queue 30
- List gives a FIFO queue; use BRPOP for blocking wait. For at-least-once processing and consumer groups, consider Streams.
Core Mechanism / Behavior
- Encoding: Redis may store a type in a more compact encoding (e.g. small hash as ziplist). Key and value sizes affect memory; very large values are less efficient.
- Atomicity: Single commands are atomic; multi-key operations use transactions (MULTI/EXEC) or Lua for atomicity across keys.
- TTL: Only the key has TTL; for Hash/List/Set/ZSet the whole key expires together. No per-element TTL except with a separate key per element (or use Sorted Set with score = expiry and a cleanup job).
| Type | Typical use | Commands (examples) |
|---|---|---|
| String | Cache, counter, flag | GET/SET/INCR, SETEX |
| Hash | Object with fields | HSET/HGET/HGETALL/HINCRBY |
| List | Queue, feed, recent-N | LPUSH/RPOP, LTRIM, BRPOP |
| Set | Membership, uniqueness | SADD/SMEMBERS/SISMEMBER, SINTER |
| ZSet | Rank, leaderboard, time-series | ZADD/ZRANGE/ZRANGEBYSCORE/ZINCRBY |
Key Rules
- Use String for a single value or serialized object; use Hash when you need to read/update individual attributes of one entity.
- Use List for simple queues or recent-N; use Streams when you need consumer groups and message history. Use ZSet when order by score (rank or time) is required.
- Set a TTL on cache keys to avoid unbounded growth; use a consistent key naming scheme (e.g.
entity:idorentity:id:field) for clarity and patterns (e.g. SCAN).
What's Next
See Cache-Aside Pattern and Caching Pitfalls for cache usage. See Expiration Strategy for TTL design. See Rate Limiting for counters and sliding window (String/ZSet).