Essential Redis commands organized by data type with syntax examples. Covers strings, hashes, lists, sets, sorted sets, streams, pub/sub, transactions, and common production patterns.
# Connect to local Redis
redis-cli
# Connect to remote Redis with auth
redis-cli -h 10.0.0.5 -p 6379 -a mypassword
# Connect with TLS
redis-cli --tls -h redis.example.com -p 6380
# Check server health
127.0.0.1:6379> PING
PONG
# Get memory usage info
127.0.0.1:6379> INFO memory
Strings
Command
Description
SET key value
Set a key to a string value
GET key
Get the value of a key
MSET k1 v1 k2 v2
Set multiple keys atomically
MGET k1 k2 k3
Get multiple values at once
INCR key
Increment integer value by 1
INCRBY key 10
Increment integer value by 10
DECR key
Decrement integer value by 1
DECRBY key 5
Decrement integer value by 5
APPEND key " more"
Append string to existing value
STRLEN key
Get string length of value
SETEX key 60 value
Set with 60-second expiration
SETNX key value
Set only if key does not exist
GETSET key newval
Set new value, return old value
GETRANGE key 0 4
Get substring (bytes 0 through 4)
String Examples
# Basic set and get
SET user:name "Alice"
GET user:name # "Alice"
# Set with expiration (cache for 5 minutes)
SET api:cache:result '{"status":"ok"}' EX 300
# Atomic counter
SET page:views 0
INCR page:views # 1
INCRBY page:views 10 # 11
# Set only if not exists (simple lock)
SETNX lock:resource "owner-123"
# Bulk operations
MSET city "Berlin" country "DE" lang "en"
MGET city country lang # "Berlin" "DE" "en"
Hashes
Command
Description
HSET key field value
Set a field in a hash
HGET key field
Get a hash field value
HMSET key f1 v1 f2 v2
Set multiple hash fields
HMGET key f1 f2 f3
Get multiple hash field values
HGETALL key
Get all fields and values
HDEL key field
Delete a field from a hash
HEXISTS key field
Check if field exists (1 or 0)
HINCRBY key field 5
Increment integer field by 5
HINCRBYFLOAT key field 1.5
Increment float field by 1.5
HLEN key
Get number of fields in hash
HKEYS key
Get all field names
HVALS key
Get all field values
HSETNX key field val
Set field only if it does not exist
Hash Examples
# Store a user object
HSET user:100 name "Alice" email "alice@dev.io" role "admin"
# Read specific fields
HGET user:100 name # "Alice"
HMGET user:100 name role # "Alice" "admin"
# Get all fields
HGETALL user:100
# "name" "Alice" "email" "alice@dev.io" "role" "admin"
# Increment a numeric field
HSET user:100 login_count 0
HINCRBY user:100 login_count 1 # 1
# Check field existence
HEXISTS user:100 email # 1
HEXISTS user:100 phone # 0
Lists
Command
Description
LPUSH key v1 v2
Push values to head (left) of list
RPUSH key v1 v2
Push values to tail (right) of list
LPOP key
Remove and return first element
RPOP key
Remove and return last element
LRANGE key 0 -1
Get all elements in list
LLEN key
Get list length
LINDEX key 0
Get element at index 0
LINSERT key BEFORE piv val
Insert before pivot element
LINSERT key AFTER piv val
Insert after pivot element
LREM key 2 val
Remove first 2 occurrences of val
LTRIM key 0 99
Trim list to first 100 elements
BLPOP key 30
Blocking pop from head (30s timeout)
BRPOP key 30
Blocking pop from tail (30s timeout)
LMOVE src dst LEFT RIGHT
Move element between lists (6.2+)
List Examples
# Build a task queue
RPUSH queue:jobs "job:1" "job:2" "job:3"
# Worker pops from the left (FIFO)
LPOP queue:jobs # "job:1"
# Blocking pop (worker waits for new jobs)
BLPOP queue:jobs 0 # blocks until a job arrives
# Recent activity feed (keep last 50 items)
LPUSH feed:user:42 "posted a comment"
LTRIM feed:user:42 0 49
LRANGE feed:user:42 0 9 # latest 10 items
# Stack behavior (LIFO)
LPUSH stack:undo "action1" "action2"
LPOP stack:undo # "action2"
# Set a cache key with 5-minute TTL
SET cache:query:abc "result data" EX 300
TTL cache:query:abc # 300
# Check remaining time
TTL cache:query:abc # e.g. 287
# Remove expiry (keep forever)
PERSIST cache:query:abc
TTL cache:query:abc # -1
# Safe iteration (production-friendly)
SCAN 0 MATCH user:* COUNT 100
# Returns: cursor + batch of matching keys
# Continue with returned cursor until 0
# Check data type
TYPE user:100 # "hash"
TYPE queue:jobs # "list"
Pub/Sub
Command
Description
SUBSCRIBE ch1 ch2
Subscribe to channels
PUBLISH channel "msg"
Publish message to a channel
UNSUBSCRIBE ch1
Unsubscribe from a channel
PSUBSCRIBE news.*
Subscribe to pattern-matched channels
PUNSUBSCRIBE news.*
Unsubscribe from pattern
PUBSUB CHANNELS
List active channels
PUBSUB NUMSUB ch1
Get subscriber count for channel
Pub/Sub Examples
# Terminal 1: Subscribe to notifications
SUBSCRIBE notifications
# Waiting for messages...
# Terminal 2: Publish a message
PUBLISH notifications "User signed up"
# (integer) 1 -- one subscriber received it
# Pattern subscribe (all event channels)
PSUBSCRIBE events.*
# Matches: events.login, events.purchase, events.logout
# Check active channels
PUBSUB CHANNELS
PUBSUB NUMSUB notifications # "notifications" "1"
Transactions
Command
Description
MULTI
Start a transaction block
EXEC
Execute all queued commands
DISCARD
Discard queued commands, exit transaction
WATCH key1 key2
Watch keys for changes (optimistic lock)
UNWATCH
Cancel all watched keys
Transaction Examples
# Basic transaction: transfer funds
MULTI
DECRBY account:alice 100
INCRBY account:bob 100
EXEC
# Both commands execute atomically
# Optimistic locking with WATCH
WATCH account:alice
balance = GET account:alice # "500"
MULTI
SET account:alice 400
SET account:bob 600
EXEC
# Returns nil if account:alice was modified by another client
# Abort a transaction
MULTI
SET key1 "val1"
DISCARD # all queued commands discarded
Streams
Command
Description
XADD stream * field val
Append entry with auto-generated ID
XADD stream maxlen 1000 * f v
Append and cap stream at 1000 entries
XREAD COUNT 10 STREAMS s1 0
Read 10 entries from start
XREAD BLOCK 5000 STREAMS s1 $
Block-read new entries (5s timeout)
XRANGE stream - +
Get all entries in stream
XRANGE stream - + COUNT 5
Get first 5 entries
XLEN stream
Get number of entries
XGROUP CREATE s grp 0
Create a consumer group
XREADGROUP GROUP grp c1 COUNT 5 STREAMS s >
Read as consumer c1 in group
XACK stream grp id
Acknowledge processed message
XPENDING stream grp
View pending (unacked) messages
XINFO STREAM stream
Get stream metadata
XTRIM stream MAXLEN 500
Trim stream to 500 entries
Stream Examples
# Add events to a stream
XADD events * action "login" user "alice"
# "1707667200000-0"
XADD events * action "purchase" user "bob" amount "49.99"
# "1707667200001-0"
# Read all events
XRANGE events - +
# Create a consumer group starting from the beginning
XGROUP CREATE events workers 0
# Consumer reads pending messages
XREADGROUP GROUP workers worker-1 COUNT 5 STREAMS events >
# Acknowledge after processing
XACK events workers "1707667200000-0"
# Check unprocessed messages
XPENDING events workers
Common Patterns
Caching (Cache-Aside)
Check cache first. On miss, query the database, then store the result with a TTL to prevent stale data.
# Read-through cache pseudocode
value = GET "cache:user:123"
if value is nil:
value = db.query("SELECT * FROM users WHERE id=123")
SET "cache:user:123" value EX 300 # 5-minute TTL
return value
# Invalidate on write
DEL "cache:user:123"
Rate Limiting (Sliding Window)
Use sorted sets with timestamps to enforce per-user request limits with a sliding time window.
# Allow 100 requests per 60 seconds
MULTI
ZREMRANGEBYSCORE ratelimit:user:42 0 (NOW-60)
ZADD ratelimit:user:42 NOW NOW
ZCARD ratelimit:user:42
EXPIRE ratelimit:user:42 60
EXEC
# If ZCARD result > 100, reject the request
Session Storage
Store user sessions as hashes with automatic expiration. Fast reads and writes for web session data.
# Create session
HSET session:tok123 user_id 42 role "admin" ip "10.0.0.1"
EXPIRE session:tok123 3600 # 1-hour TTL
# Read session data
HGETALL session:tok123
# Refresh TTL on each request
EXPIRE session:tok123 3600
# Logout: destroy session
DEL session:tok123
Leaderboard
Sorted sets provide O(log N) inserts and efficient range queries for real-time leaderboards.
# Add player scores
ZADD leaderboard 1500 "alice" 1200 "bob" 1800 "carol"
# Top 5 with scores
ZREVRANGE leaderboard 0 4 WITHSCORES
# Player rank (0-indexed, highest first)
ZREVRANK leaderboard "alice" # 1
# Increment score after an event
ZINCRBY leaderboard 100 "bob" # 1300
Frequently Asked Questions
What are the main data types in Redis?
Redis supports several core data types: Strings (binary-safe text or numbers), Lists (ordered collections of strings), Sets (unordered collections of unique strings), Sorted Sets (sets ordered by a score), Hashes (field-value maps similar to objects), Streams (append-only log structures), and additional types like Bitmaps, HyperLogLogs, and Geospatial indexes. Each type has specialized commands optimized for its access patterns.
What is the difference between DEL and UNLINK in Redis?
DEL removes keys synchronously, blocking the server until the operation completes. For large keys (big lists, sets, or hashes), this can cause noticeable latency. UNLINK (available since Redis 4.0) removes keys asynchronously by unlinking them from the keyspace immediately and reclaiming memory in a background thread. Use UNLINK for large keys in production to avoid blocking the main Redis thread.
How do Redis Streams differ from Pub/Sub?
Redis Pub/Sub is fire-and-forget: messages are delivered to subscribers in real time but are lost if no subscriber is listening. Redis Streams (introduced in Redis 5.0) are persistent, append-only log structures that store messages with unique IDs. Streams support consumer groups for load-balanced processing, message acknowledgment, and the ability to read historical messages. Use Pub/Sub for ephemeral notifications and Streams for reliable message processing that requires durability and replay.
How should I use KEYS vs SCAN in production?
Never use the KEYS command in production because it scans the entire keyspace in a single blocking operation, which can freeze your Redis instance for seconds on large databases. Instead, use SCAN with a cursor-based approach. SCAN incrementally iterates through keys without blocking, returning a small batch per call. Combine it with MATCH for pattern filtering and COUNT to hint at batch size. For hash, set, and sorted set iteration, use HSCAN, SSCAN, and ZSCAN respectively.