In-Memory Data Store

Redis

The lightning-fast, open-source in-memory data structure server. Master data types, caching patterns, Pub/Sub messaging, and production configuration.

Concepts Data Types Setup Guide Usage Best Practices FAQ

Core Concepts

Understanding Redis as a data structure server.

In-Memory Store

Redis stores all data in RAM for sub-millisecond read/write latency. It supports optional persistence to disk via RDB snapshots (point-in-time) and AOF logs (append-only file).

Single-Threaded Event Loop

Redis processes commands sequentially on a single thread using an event-driven I/O model. This eliminates lock contention and makes every operation atomic by default.

Persistence Options

RDB: Periodic snapshots — fast restarts, possible data loss. AOF: Logs every write — durable, larger files. RDB+AOF: Combine both for maximum durability with fast recovery.

Pub/Sub Messaging

Built-in publish/subscribe messaging where publishers send messages to channels without knowing who listens. Ideal for real-time notifications, chat systems, and event broadcasting.

TTL & Expiration

Every key can have a Time-To-Live (TTL) in seconds or milliseconds. Redis automatically evicts expired keys — essential for caching, sessions, and rate limiting.

Cluster & Sentinel

Redis Cluster: Automatic sharding across multiple nodes for horizontal scaling. Sentinel: High availability with automatic failover for master-replica setups.

Data Types & Commands

Redis is a "data structure server" — choosing the right type is critical for performance.

Type Description Key Commands Use Cases
StringsText, numbers, or binary (up to 512MB)SET, GET, INCR, DECR, MSETCaching, counters, session tokens
HashesMap of field-value pairs (like an object)HSET, HGET, HGETALL, HDELUser profiles, product metadata
ListsOrdered collection (doubly linked list)LPUSH, RPUSH, LPOP, LRANGEQueues, activity feeds, chat logs
SetsUnordered collection of unique stringsSADD, SMEMBERS, SINTER, SDIFFTags, unique visitors, friends lists
Sorted SetsSets with a score for orderingZADD, ZRANGE, ZRANK, ZREMLeaderboards, rankings, priority queues
StreamsAppend-only log with consumer groupsXADD, XREAD, XREADGROUPEvent sourcing, message broking
HyperLogLogProbabilistic cardinality counterPFADD, PFCOUNT, PFMERGEUnique visitor counting at scale

Setup Guide

Get Redis running locally in under a minute.

Docker (Recommended)

# Start Redis container
docker run -d \
  --name redis-dev \
  -p 6379:6379 \
  redis:7-alpine

# Connect with CLI
docker exec -it redis-dev redis-cli

# Verify
127.0.0.1:6379> PING
PONG

macOS

# Install via Homebrew
brew install redis

# Start as a service
brew services start redis

# Or start manually
redis-server

# Connect
redis-cli ping

Ubuntu/Debian

# Install from apt
sudo apt update
sudo apt install redis-server

# Start and enable
sudo systemctl start redis
sudo systemctl enable redis

# Verify
redis-cli ping

Usage Examples

Practical patterns for caching, sessions, Pub/Sub, and rate limiting.

redis-cli
# Strings — cache a JSON payload
SET user:42 '{"name":"Alice"}' EX 3600
GET user:42

# Hash — user profile
HSET user:42 name "Alice" role "admin"
HGETALL user:42

# Sorted Set — leaderboard
ZADD leaderboard 1500 "player:1"
ZADD leaderboard 2300 "player:2"
ZREVRANGE leaderboard 0 9 WITHSCORES

# Pub/Sub (Terminal 1: subscribe)
SUBSCRIBE notifications
# Pub/Sub (Terminal 2: publish)
PUBLISH notifications "New order received!"
Python (redis-py)
# pip install redis
import redis, json

r = redis.Redis(host='localhost', port=6379, db=0)

# Cache-aside pattern
def get_user(user_id):
  cached = r.get(f"user:{user_id}")
  if cached:
    return json.loads(cached)
  user = db.query(f"SELECT * FROM users WHERE id={user_id}")
  r.setex(f"user:{user_id}", 3600, json.dumps(user))
  return user

# Rate limiter (sliding window)
def is_rate_limited(ip, limit=100, window=60):
  key = f"rate:{ip}"
  current = r.incr(key)
  if current == 1:
    r.expire(key, window)
  return current > limit

Best Practices

Set maxmemory

Always configure maxmemory and an eviction policy (allkeys-lru is recommended for caching). Without this, Redis will consume all available RAM and crash.

Key Naming Convention

Use a consistent pattern: entity:id:field (e.g., user:42:profile). This makes keys self-documenting and enables pattern scanning with SCAN.

Always Set TTL

Use EXPIRE or SETEX for cache data. Without TTLs, memory fills up with stale data. Review and clean orphaned keys regularly.

Avoid Giant Keys

Large hashes, lists, or sets can block the single-threaded event loop. Keep collections under 10,000 members. Use SCAN instead of KEYS * in production.

Use Pipelining

Batch multiple commands into a single network round-trip using pipelines. This dramatically reduces latency overhead for bulk operations.

Monitor with INFO

Regularly check INFO memory, INFO stats, and SLOWLOG GET to identify memory issues, hit/miss ratios, and slow commands. Use RedisInsight for visual monitoring.

Scaling & Production

Redis Cluster

Distribute data across 16,384 hash slots spread over 3+ master nodes. Each master has 1+ replicas for failover. Supports automatic resharding — add nodes and migrate slots with redis-cli --cluster reshard.

Sentinel HA

For simpler setups, use Redis Sentinel (3+ sentinel processes) for automatic master failover. Sentinels monitor the master, elect a new one on failure, and redirect clients. Good for single-shard HA without full Cluster complexity.

Read Replicas

Scale reads by adding replicas. Configure clients with READONLY mode to route GET operations to replicas. Replication is asynchronous — eventual consistency. Use WAIT command for synchronous replication when needed.

Memory Management

Set maxmemory and choose an eviction policy: allkeys-lru (cache), volatile-ttl (expire soonest first), or noeviction (queue). Monitor fragmentation ratio — restart or use MEMORY PURGE if >1.5.

Client-Side Caching

Redis 6+ supports server-assisted client-side caching via CLIENT TRACKING. The server invalidates client-local caches when keys change, reducing round trips by 10–100× for hot keys.

Scaling Benchmarks

Single Redis instance: 100K–300K ops/sec (GET/SET). A 6-node cluster (3 masters + 3 replicas) handles 1M+ ops/sec. Use pipelining (PIPELINE) to batch commands and reduce RTT overhead by 10×.

Frequently Asked Questions

Redis vs Memcached — when to use which?
Use Redis when you need data structures beyond simple key-value (hashes, sets, sorted sets), persistence, Pub/Sub, or Lua scripting. Use Memcached for pure cache-only use cases where you need multi-threaded performance and simple string caching at massive scale.
Should I use RDB or AOF persistence?
RDB is best for backups and fast restarts (potential data loss of minutes). AOF is best for durability (potential data loss of 1 second with appendfsync everysec). For production, use both RDB + AOF together.
How do I handle cache invalidation?
Use a cache-aside pattern: read from cache first, fall back to database on miss, and write-through on updates. Invalidate cache entries with DEL when the source data changes. For complex scenarios, use Pub/Sub to broadcast invalidation events.
What is the Redis licensing situation?
As of 2025, Redis transitioned to AGPLv3 from the BSD license. It remains fully open-source but cloud providers offering managed Redis services must comply with AGPLv3 requirements. The community fork Valkey (maintained by the Linux Foundation) continues under the BSD license.
Redis Cluster vs Redis Sentinel?
Cluster provides horizontal scaling by automatically sharding data across nodes (each node holds a subset of keys). Sentinel provides high availability for a single-shard setup by monitoring masters and performing automatic failover to replicas. Choose Cluster when you need more data capacity than one node can hold.