Redis Data Types and Commands

intermediate redis data-types in-memory cache commands

A lot of people think Redis is “just a cache.” That’s selling it short. Redis is an in-memory data structure store — it gives us strings, hashes, lists, sets, sorted sets, streams, and more. Each data type has its own set of commands, and picking the right one can make a huge difference in how we solve a problem.

Let’s walk through each one.

Strings

The simplest type. A string in Redis can hold text, numbers, or even binary data (up to 512 MB). But we mostly use it for simple key-value caching and counters.

# Basic set and get
SET user:name "Manish"
GET user:name              # "Manish"

# Set with expiry (seconds)
SETEX session:abc123 3600 "user_42"   # expires in 1 hour

# Set only if key doesn't exist (useful for locks)
SETNX lock:order:99 "worker_1"       # returns 1 if set, 0 if already exists

# Atomic counter — no race conditions
SET page:views 0
INCR page:views            # 1
INCR page:views            # 2
INCRBY page:views 10       # 12

Use cases: simple cache, session tokens, counters, rate limiting.

Hashes

Think of a hash as a mini object or dictionary stored under one key. Instead of serializing a whole JSON object into a string, we can store each field separately — and update individual fields without rewriting the whole thing.

# Store a user profile
HSET user:42 name "Manish" age 28 city "Pune"

# Get a single field
HGET user:42 name          # "Manish"

# Get all fields
HGETALL user:42            # name, Manish, age, 28, city, Pune

# Update just one field
HSET user:42 age 29

# Increment a numeric field
HINCRBY user:42 age 1      # 30

Use cases: user profiles, product details, any object with multiple fields that we update independently.

Lists

Redis lists are linked lists — fast push/pop at both ends, but slow random access in the middle. They’re perfect for queues and “recent items” feeds.

# Build a queue (push left, pop right = FIFO)
LPUSH queue:emails "email_1"
LPUSH queue:emails "email_2"
RPOP queue:emails           # "email_1" (first in, first out)

# Blocking pop — waits up to 5 seconds for a new item
BLPOP queue:emails 5

# Recent activity feed (keep last 100 items)
LPUSH feed:user:42 "liked a post"
LTRIM feed:user:42 0 99    # trim to 100 items
LRANGE feed:user:42 0 9    # get the 10 most recent

Use cases: message queues, recent activity, job queues, chat history.

Sets

Unordered collections of unique values. Sets shine when we need to check membership or compute intersections/unions.

# Track tags on a post
SADD post:1:tags "redis" "database" "caching"
SADD post:2:tags "redis" "performance" "caching"

# Check if a tag exists
SISMEMBER post:1:tags "redis"    # 1 (true)

# All tags on post 1
SMEMBERS post:1:tags

# Tags common to both posts
SINTER post:1:tags post:2:tags   # "redis", "caching"

# All unique tags across both posts
SUNION post:1:tags post:2:tags

Use cases: tags, unique visitors, mutual friends, “already processed” tracking.

Sorted Sets

Like sets, but every member has a score. Redis keeps them sorted by score automatically. This is what makes leaderboards and priority queues trivial.

# Leaderboard
ZADD leaderboard 1500 "alice"
ZADD leaderboard 2300 "bob"
ZADD leaderboard 1800 "charlie"

# Top 3 players (highest score first)
ZREVRANGE leaderboard 0 2 WITHSCORES
# bob 2300, charlie 1800, alice 1500

# What's alice's rank? (0-based, highest first)
ZREVRANK leaderboard "alice"   # 2

# Increment score
ZINCRBY leaderboard 1000 "alice"   # alice now at 2500

Use cases: leaderboards, priority queues, rate limiting (sliding window), scheduling.

Streams

Streams are Redis’s answer to event logs and message queues. Unlike Pub/Sub, streams persist messages and support consumer groups — so we can have multiple consumers processing messages reliably.

# Add events to a stream
XADD orders * product "laptop" qty 1
XADD orders * product "mouse" qty 3

# Read all entries
XREAD COUNT 10 STREAMS orders 0

# Consumer groups — multiple workers processing orders
XGROUP CREATE orders workers 0
XREADGROUP GROUP workers worker-1 COUNT 1 STREAMS orders >

Use cases: event sourcing, audit logs, reliable message queues, activity streams.

HyperLogLog

This one is clever. HyperLogLog counts approximate unique items using very little memory — about 12 KB regardless of how many items we add. The trade-off is it’s ~0.81% off from the exact count.

# Count unique visitors
PFADD visitors:today "user_1" "user_2" "user_3"
PFADD visitors:today "user_1"    # duplicate, not counted again
PFCOUNT visitors:today            # 3

# Merge multiple days
PFMERGE visitors:week visitors:mon visitors:tue visitors:wed

Use cases: unique visitor counting, unique search queries, cardinality estimation.

Bitmaps

Bitmaps let us set individual bits on a string. Each bit is either 0 or 1. Super memory-efficient for tracking boolean states across millions of users.

# Track daily active users (user ID = bit offset)
SETBIT active:2026-03-31 42 1    # user 42 was active today
SETBIT active:2026-03-31 99 1    # user 99 was active today

# Was user 42 active?
GETBIT active:2026-03-31 42      # 1

# How many users were active today?
BITCOUNT active:2026-03-31       # 2

Use cases: feature flags, daily active users, bloom filter implementation.

Data Type Comparison

Type Best For Key Commands
String Cache, counters, locks SET, GET, INCR, SETNX
Hash Objects, user profiles HSET, HGET, HGETALL
List Queues, recent items LPUSH, RPOP, BLPOP
Set Unique items, tags SADD, SINTER, SUNION
Sorted Set Leaderboards, rankings ZADD, ZRANGE, ZREVRANK
Stream Event logs, message queues XADD, XREAD, XREADGROUP
HyperLogLog Unique counts (~0.81% error) PFADD, PFCOUNT, PFMERGE
Bitmap Feature flags, DAU tracking SETBIT, GETBIT, BITCOUNT

Internal Encodings (Brief)

Redis doesn’t always use the “obvious” data structure under the hood. For small data, it uses compact encodings to save memory:

  • Small hashes/lists/sets use listpack (previously ziplist) — a flat, compact byte array. Much less memory than a real hash table or linked list.
  • Large sorted sets use a skiplist — a probabilistic data structure that gives us O(log n) lookups, similar to a balanced tree.
  • Large hashes switch to a real hashtable once they exceed a threshold.

We usually don’t need to worry about this — Redis picks the best encoding automatically. But it’s good to know for interviews when someone asks “how does Redis store a sorted set internally?”