Guide contents

Lesson 33 of 129

Redis and Memcached

Redis and Memcached are in-memory key-value servers used mainly as caches. Memcached stores opaque values under string keys. Redis stores typed data structures, can persist data to disk, and provides replication and clustering. Both serve requests from RAM with latencies well under a millisecond on a local network.

Redis data structures

Redis values have a type, and commands operate on the type on the server, so clients do not need to read, modify, and write the whole value.

Type Description Typical use
String bytes, up to 512 MB; integer operations such as INCR cached objects, counters, locks
Hash field-to-value map under one key object fields, partial updates
List ordered list, push/pop at both ends queues, recent items
Set unordered unique members tags, unique visitors, set operations
Sorted set members ordered by a score, O(log n) insert leaderboards, priority queues, rate-limit windows
Stream append-only log with consumer groups event streams
Bitmap, HyperLogLog, Geo bit operations, approximate cardinality, geospatial queries flags, unique counts, proximity

Keys can carry a TTL (EXPIRE, SET ... EX). Expired keys are removed lazily on access and by a periodic sampling process.

Single-threaded command execution

Redis executes commands on one thread. Each command is atomic, because no other command runs concurrently, and no locks are needed inside the data structures. The event loop multiplexes many client connections using I/O readiness notification (epoll and similar). Newer versions can use additional threads for network reading and writing, but command execution stays serial.

Consequences:

  • Throughput is bounded by one core for command execution. Scale further with more instances (sharding).
  • A slow command blocks all clients. KEYS *, large SMEMBERS, and long Lua scripts are hazards; use incremental iteration (SCAN) instead.
  • Multi-step atomicity is available through MULTI/EXEC and Lua scripts, which run without interleaving.

Persistence

By default memory is volatile. Redis offers two persistence mechanisms, usable together.

RDB snapshot AOF (append-only file)
What is stored point-in-time binary dump of the dataset log of every write command
Trigger periodic rules (every N seconds if M changes), or manual each write appended; fsync policy configurable
Data loss on crash changes since the last snapshot depends on fsync: every write, every second, or left to the OS
Restart speed fast (load the dump) slower (replay the log)
File size compact larger; periodically rewritten to compact it

RDB snapshots are produced by a forked child process, so the parent keeps serving requests. The child sees a copy-on-write view of memory: pages the parent modifies during the snapshot are duplicated, so memory use can grow with the write rate while a snapshot or AOF rewrite runs. AOF with fsync every second is a common compromise between durability and speed. Persistence in Redis is asynchronous with respect to clients unless configured to fsync on every write, so Redis is not a replacement for a durable database by default.

Replication and Sentinel

Redis replication is leader-follower (called primary and replica). A replica connects to the primary, receives an initial snapshot, and then a stream of write commands. Replication is asynchronous by default, so a failover can lose the most recent writes. Replicas serve reads, which may be stale.

graph LR
    P["Primary"] -->|"async command stream"| R1["Replica 1"]
    P -->|"async command stream"| R2["Replica 2"]
    S1["Sentinel 1"] -.->|monitor| P
    S2["Sentinel 2"] -.->|monitor| P
    S3["Sentinel 3"] -.->|monitor| P

Redis Sentinel provides high availability for a non-clustered deployment. A group of Sentinel processes monitors the primary and replicas. When a configurable quorum of Sentinels agree the primary is unreachable, it is marked objectively down. The Sentinels then elect one of themselves as leader, which requires votes from a majority of all Sentinels, and that leader runs the failover: promote a replica, reconfigure the others, and inform clients. Clients ask Sentinels for the current primary address. Deploy at least three Sentinels, on independent machines, so a majority survives one failure. See leader election for the underlying problem.

Redis Cluster

Redis Cluster shards data across multiple primaries. The key space is divided into 16384 hash slots. The slot of a key is CRC16(key) mod 16384. Each primary owns a subset of slots, and each primary can have replicas.

  • A client sends a command to any node. If that node does not own the slot, it replies with a redirection (MOVED slot host:port). Cluster-aware clients cache the slot-to-node map.
  • Resharding moves slots between nodes with key migration, while the cluster is online.
  • Nodes exchange state using a gossip protocol, and replicas are promoted when a primary is detected as failed by a majority of primaries.
  • Multi-key commands work only when all keys hash to the same slot. Hash tags allow this: only the part of the key inside {...} is hashed, so {user42}:cart and {user42}:profile share a slot.

Redis Cluster does not provide strong consistency. Replication between a primary and its replicas is asynchronous, so a primary that fails right after acknowledging a write can lose it, and a primary partitioned away from the majority of primaries stops accepting writes after a timeout.

Compared with consistent hashing, fixed slots make ownership an explicit table: moving a slot moves a known set of keys.

Memcached

Memcached is a multi-threaded in-memory cache. Its model is deliberately small:

  • Keys map to opaque byte values, with a size limit (1 MB by default per item), and a TTL.
  • Operations: get, set, add, replace, delete, incr/decr, cas (compare-and-swap using a version token).
  • Memory is managed with slab allocation: memory is divided into size classes to avoid fragmentation, and each class has its own LRU.
  • No persistence, no replication, no server-side clustering. Clients distribute keys across servers, typically using consistent hashing. Servers do not know about each other.
  • Multi-threaded, so a single instance can use several cores.

Redis compared with Memcached

Aspect Redis Memcached
Data types strings, hashes, lists, sets, sorted sets, streams, and more opaque strings
Persistence RDB, AOF none
Replication and failover built in (replicas, Sentinel, Cluster) none built in
Clustering server-side (Cluster) client-side sharding
Command execution single-threaded multi-threaded
Eviction configurable policies (LRU/LFU approximations, random, TTL-based, or none) LRU per slab class
Atomic operations commands, transactions, Lua scripts incr/decr, cas
Typical fit cache plus data structures, counters, queues, leaderboards, rate limiting simple, large, multi-threaded object cache

Memcached suits a plain cache of serialized objects where multi-core efficiency and simplicity matter. Redis suits cases needing server-side structures, persistence, or replication.

Eviction when memory is full

Redis has a maxmemory limit and a maxmemory-policy. Policies include noeviction (writes fail), allkeys-lru, allkeys-lfu, allkeys-random, and volatile-* variants that only evict keys with a TTL. For a pure cache, an allkeys-* policy is typical. See cache eviction policies.

Interview questions

  • Why is single-threaded Redis fast? Data is in memory, commands are short, there is no lock contention, and an event loop handles many connections. The trade-off is that one slow command delays every client.
  • What is the difference between RDB and AOF? RDB is a periodic point-in-time snapshot: compact and quick to load, but changes since the last snapshot are lost on a crash. AOF logs each write and can lose at most about a second of data with per-second fsync, at the cost of a larger file and slower restart.
  • How does Redis Cluster locate a key? It computes CRC16(key) mod 16384 to get the slot, and a slot-to-node table identifies the owner. A node that does not own the slot returns a MOVED redirection.
  • Can a Redis failover lose data? Yes. Replication is asynchronous, so writes acknowledged by the old primary but not yet received by the promoted replica are lost.