logo Fonnpo

Contact Me
May 30, 2026 3 min read Fonnpo

The Complete Redis Guide

Redis is a high-performance in-memory key-value store with rich data structures including String, Hash, List, Set, and ZSet. This guide covers installation, all core data types, expiration, persistence (RDB/AOF/Hybrid), Pub/Sub, transactions, Pipeline, common use cases like distributed locks and leaderboards, and the three cache failure modes — everything you need to use Redis in production.

#Redis#Database#Cache

Redis is an in-memory key-value store that supports rich data structures. It is commonly used for caching, message queues, distributed locks, leaderboards, and more. This guide starts from installation and covers all core data types and real-world practices.

Installation and Connection

macOS

Bash
        brew install redis
brew services start redis   # start in background
redis-cli                   # open interactive client

    

Linux (Ubuntu / Debian)

Bash
        sudo apt update && sudo apt install redis-server
sudo systemctl start redis
redis-cli

    
Bash
        # Start container
docker run -d --name redis -p 6379:6379 redis:7-alpine

# Open CLI
docker exec -it redis redis-cli

    

Basic Connection and Verification

Bash
        redis-cli -h 127.0.0.1 -p 6379

# Test connectivity
PING              # returns PONG

# If a password is set
AUTH your_password

# Select a database (default 0, 16 total)
SELECT 1

# Count keys in current database
DBSIZE

# List all keys (avoid on production — can block)
KEYS *

# Pattern scan (use SCAN instead of KEYS on production)
SCAN 0 MATCH user:* COUNT 100

    

Data Types Overview

TypeTypical Use Cases
StringCache, counters, distributed locks
HashObject storage (user profiles, product details)
ListMessage queue, activity feed, operation log
SetDeduplication, mutual friends, lottery
ZSet (Sorted Set)Leaderboards, weighted queues
StreamPersistent message queue (lightweight Kafka alternative)
BitmapUser check-in, Bloom filter
HyperLogLogLarge-scale UV estimation (approximate)

String

String is the most basic type. It can store text, numbers, or binary data (up to 512 MB).

Bash
        # Set and get
SET name "Alice"
GET name              # "Alice"

# Set with expiration (seconds)
SET token "abc123" EX 3600

# Set only if key does not exist (basis of distributed lock)
SET lock "1" NX EX 10

# Batch operations
MSET k1 v1 k2 v2 k3 v3
MGET k1 k2 k3

# Append to value
APPEND name " Smith"  # "Alice Smith"

# Numeric operations
SET counter 0
INCR counter          # 1
INCRBY counter 5      # 6
DECR counter          # 5
DECRBY counter 2      # 3

# Float increment
SET price 9.99
INCRBYFLOAT price 0.5  # 10.49

# Get string length
STRLEN name

# Get old value and set new value atomically
GETSET name "Bob"     # returns "Alice Smith", sets "Bob"

    
Collapse

Hash

Hash is ideal for storing structured objects, avoiding repeated serialization and deserialization.

Bash
        # Set fields
HSET user:1 name "Alice" age 25 email "alice@example.com"

# Get a single field
HGET user:1 name      # "Alice"

# Get all fields and values
HGETALL user:1

# Get all field names
HKEYS user:1

# Get all values
HVALS user:1

# Number of fields
HLEN user:1

# Check if a field exists
HEXISTS user:1 email   # 1 (exists)

# Delete a field
HDEL user:1 email

# Get multiple fields at once
HMGET user:1 name age

# Increment a numeric field
HINCRBY user:1 age 1

# Set only if field does not exist
HSETNX user:1 role "admin"

    
Collapse

List

List is a doubly-linked list. It supports push and pop from both ends — great for queues and stacks.

Bash
        # Push to the left (head)
LPUSH logs "event1" "event2" "event3"

# Push to the right (tail)
RPUSH queue "task1" "task2"

# Pop from the left
LPOP logs

# Pop from the right
RPOP queue

# Blocking pop (0 = wait forever — great for consumer pattern)
BLPOP queue 0
BRPOP queue 30     # wait up to 30 seconds

# View a range (0 -1 = all)
LRANGE logs 0 -1

# Get element at index
LINDEX logs 0

# Get list length
LLEN logs

# Trim to a range (keep only first 100 elements)
LTRIM logs 0 99

# Insert before or after an element
LINSERT logs BEFORE "event2" "new-event"

# Remove matching elements
LREM logs 2 "event1"  # remove 2 occurrences of "event1"

    
Collapse

Classic use: message queue

Bash
        # Producer
RPUSH queue "msg1"

# Consumer (blocking — returns immediately when a message arrives)
BLPOP queue 0

    

Set

Set is an unordered collection of unique members. It supports set operations.

Bash
        # Add members
SADD tags "redis" "cache" "nosql"

# Check membership
SISMEMBER tags "redis"   # 1

# Get all members
SMEMBERS tags

# Set size
SCARD tags

# Remove a member
SREM tags "nosql"

# Get random members (no removal)
SRANDMEMBER tags 2

# Pop a random member
SPOP tags

# Set operations
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"

SUNION set1 set2       # union: a b c d
SINTER set1 set2       # intersection: b c
SDIFF set1 set2        # difference: a (in set1 but not set2)

# Store results in a new key
SUNIONSTORE result set1 set2
SINTERSTORE result set1 set2

    
Collapse

ZSet (Sorted Set)

Every member in a ZSet has a score. Members are sorted by score — perfect for leaderboards.

Bash
        # Add members (score member)
ZADD leaderboard 1000 "Alice" 850 "Bob" 1200 "Charlie"

# Get a member's score
ZSCORE leaderboard "Alice"   # 1000

# Rank by score ascending (0 = first place)
ZRANK leaderboard "Alice"    # 1 (0-indexed)

# Rank by score descending
ZREVRANK leaderboard "Alice" # 1

# Get range by rank ascending
ZRANGE leaderboard 0 -1 WITHSCORES

# Get range by rank descending
ZREVRANGE leaderboard 0 2 WITHSCORES

# Get range by score
ZRANGEBYSCORE leaderboard 800 1100 WITHSCORES

# Increment score
ZINCRBY leaderboard 100 "Alice"   # 1100

# Total member count
ZCARD leaderboard

# Count members within a score range
ZCOUNT leaderboard 900 1200

# Remove a member
ZREM leaderboard "Bob"

# Remove by rank range
ZREMRANGEBYRANK leaderboard 0 1

# Remove by score range
ZREMRANGEBYSCORE leaderboard 0 800

    
Collapse

Expiration

Bash
        # Set expiration in seconds
EXPIRE key 3600

# Set expiration in milliseconds
PEXPIRE key 3600000

# Set to a specific Unix timestamp (seconds)
EXPIREAT key 1893456000

# Check remaining TTL in seconds (-1 = no expiry, -2 = key does not exist)
TTL key

# Check remaining TTL in milliseconds
PTTL key

# Remove expiration (make permanent)
PERSIST key

    

Persistence

Redis is in-memory by default — data is lost on restart. Two persistence options exist:

RDB (Snapshot)

Periodically dumps memory to disk. The default persistence method.

Bash
        # redis.conf — save every 60s if at least 1 key changed
save 60 1
save 300 10
save 900 1

# Trigger manually
BGSAVE      # async background save
SAVE        # synchronous (blocks — avoid on production)

    

Pros: compact file, fast restore.
Cons: data between two snapshots can be lost.

AOF (Append-Only File)

Logs every write command. Replays on restart to restore data.

Bash
        # redis.conf
appendonly yes
appendfilename "appendonly.aof"

# Sync policy
appendfsync always    # sync on every write — safest, slowest
appendfsync everysec  # sync once per second (recommended — up to 1s data loss)
appendfsync no        # let the OS decide — fastest but riskiest

    

Pros: safer, at most 1 second of data loss.
Cons: larger file, slower restore.

Bash
        # redis.conf
aof-use-rdb-preamble yes

    

The AOF file starts with an RDB snapshot followed by incremental commands — combining speed and safety.

Pub/Sub

Bash
        # Subscribe to channels (blocks waiting for messages)
SUBSCRIBE news sports

# Publish a message
PUBLISH news "Breaking: Redis 8.0 released"

# Pattern subscribe
PSUBSCRIBE news.*

# Inspect subscriptions
PUBSUB CHANNELS        # list active channels
PUBSUB NUMSUB news     # subscriber count for a channel

    

Note: Pub/Sub is fire-and-forget with no persistence. For reliable messaging, use Stream or an external MQ.

Transactions

Redis transactions use MULTI / EXEC to guarantee atomic execution of a command batch (but there is no rollback on runtime errors).

Bash
        MULTI          # start transaction
SET k1 "v1"   # queued
SET k2 "v2"
INCR counter
EXEC           # execute all queued commands

# Discard the transaction
DISCARD

    

WATCH (optimistic lock):

Bash
        WATCH balance         # monitor the key

MULTI
DECRBY balance 100
EXEC                  # returns nil if balance was modified between WATCH and EXEC

    

Pipeline (Batched Requests)

Pipeline bundles multiple commands into a single round trip, significantly boosting throughput.

Bash
        # redis-cli example
redis-cli --pipe << EOF
SET k1 v1
SET k2 v2
INCR counter
EOF

    

All major client libraries support Pipeline. Example with Node.js (ioredis):

Javascript
        const pipeline = redis.pipeline()
pipeline.set('k1', 'v1')
pipeline.set('k2', 'v2')
pipeline.incr('counter')
await pipeline.exec()

    

Common Use Cases

Caching

Bash
        # Cache-Aside pattern:
# Read:  check Redis first; on miss, query DB and write to Redis
# Write: update DB first, then delete the Redis cache (ensures consistency)

SET user:1:profile "{...}" EX 300

    

Distributed Lock

Bash
        # Acquire lock: NX ensures only one client succeeds, EX prevents dead lock
SET lock:order:123 "client-uuid" NX EX 30

# Release lock: verify it is still your lock before deleting
# Use a Lua script for atomicity
EVAL "
  if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
  else
    return 0
  end
" 1 lock:order:123 client-uuid

    

Rate Limiting

Bash
        # Limit a user to 100 requests per minute
INCR rate:user:123
EXPIRE rate:user:123 60

# Atomic initialization + increment
SET rate:user:123 0 EX 60 NX   # initialize on first request
INCR rate:user:123              # increment on each request

    

Leaderboard

Bash
        # Update score
ZINCRBY leaderboard 10 "user:123"

# Get top 10
ZREVRANGE leaderboard 0 9 WITHSCORES

# Get a user's rank
ZREVRANK leaderboard "user:123"

    

Session Storage

Bash
        SET session:abc123 "{userId: 1, role: admin}" EX 86400
GET session:abc123
EXPIRE session:abc123 86400   # renew session

    

The Three Cache Failure Modes

Cache Penetration

Symptom: Requests for keys that exist in neither cache nor database always reach the database.

Solutions:

  1. Cache null values: store an empty placeholder in Redis with a short TTL
  2. Bloom filter: reject requests for keys that definitely do not exist before they reach Redis

Cache Breakdown

Symptom: A hot key expires, and a burst of concurrent requests simultaneously hit the database.

Solutions:

  1. Keep hot keys alive (no expiry, or logical expiry with async refresh)
  2. Mutex lock: only the first request rebuilds the cache; others wait

Cache Avalanche

Symptom: A large number of keys expire at the same time, overwhelming the database.

Solutions:

  1. Add random jitter to TTL values to spread expiration
  2. Keep critical data permanent with async background refresh
  3. Circuit breaker and graceful degradation to protect the database

Useful Admin Commands

Bash
        # View Redis info (memory, connections, persistence, etc.)
INFO
INFO memory
INFO server

# View slow query log
SLOWLOG GET 10

# Clear the current database (use with care)
FLUSHDB

# Clear all databases (use with care)
FLUSHALL

# Check key type
TYPE key

# Delete keys
DEL key1 key2

# Async delete (recommended for large keys — non-blocking)
UNLINK key

# Rename a key
RENAME old-key new-key

# Check memory usage of a key
MEMORY USAGE key

    
Fonnpo