← Back to the section

Redis is an in-memory store. You'd think that if the process crashes, the data is gone. In reality, Redis can save to disk, survive a server failure, and scale across multiple machines. In this article we'll look at how that works and how to pick the right settings.

Persistence: RDB and AOF

By default, Redis keeps data only in memory. If the server restarts, everything is lost. To prevent that, there are two persistence mechanisms.

RDB (Redis Database) is a snapshot: Redis takes a full "snapshot" of the data to disk in a binary format (dump.rdb). You can take a snapshot on a schedule or manually with the SAVE / BGSAVE commands. BGSAVE spawns a child process and doesn't block Redis.

# Save a snapshot manually (asynchronous, non-blocking)
BGSAVE

# Check when the last save happened
LASTSAVE

Configuration in redis.conf:

# Save a snapshot if at least 1000 keys changed within 60 seconds
save 60 1000
# Snapshot file
dbfilename dump.rdb
dir /var/lib/redis

Upside of RDB: a compact file and a fast startup after a restart. Downside: if the server crashes between snapshots, the data written in that interval is lost.

AOF (Append Only File) is a command log: every write command is appended to a file (appendonly.aof). On restart, Redis simply "replays" the whole file again.

# Enable AOF
appendonly yes
appendfilename "appendonly.aof"

# fsync policy (flush to disk):
# always  — after every command (maximum durability, slower)
# everysec — once per second (a good balance, at most 1 s of data lost)
# no      — the OS decides (fast, unreliable)
appendfsync everysec

Upside of AOF: you lose at most one second of data. Downside: the file grows and startup is slower. Redis can periodically "compact" the AOF (BGREWRITEAOF), removing redundant commands.

Short formula: for important data, enable both RDB and AOF at the same time — Redis can work with both. On startup, AOF takes priority.

Memory and eviction policies

Redis lives in RAM, which means you need to set a limit — otherwise it will eat up all of the server's memory.

# Memory limit (for example, 512 megabytes)
maxmemory 512mb

# What to do when the limit is reached — the eviction policy
maxmemory-policy allkeys-lru

Eviction policies — what Redis does when there is no memory left:

PolicyBehavior
noevictionReject writes with an error (doesn't touch the data)
allkeys-lruEvict any keys on a "least recently used" basis
volatile-lruEvict only keys with a TTL, by LRU
allkeys-randomEvict any keys at random
volatile-ttlEvict keys with the smallest remaining TTL
volatile-randomEvict keys with a TTL at random

When to choose what:

  • Redis as a cache (data can be lost) → allkeys-lru. The most common choice.
  • Redis as a cache, but only some keys have a TTL → volatile-lru.
  • Redis as a primary store (data must not be lost) → noeviction plus memory control on the application side.

In Spring Boot, when using @Cacheable, the allkeys-lru policy works transparently: Spring doesn't know about eviction — on the next access to a missing key it simply recomputes the value.

Replication: primary and replica

Replication lets you keep several copies of the data on different servers. One server is the primary (accepts writes), the rest are replicas (read-only, synchronized with the primary).

# On the replica in redis.conf (or via the CLI):
REPLICAOF 192.168.1.10 6379

The replica continuously receives a stream of changes from the primary. On the first connection, the primary runs BGSAVE and sends the snapshot, then streams the accumulated commands — that's how the replica catches up to the current state.

What replication gives you:

  • Horizontal read scaling — the application reads from replicas, reducing the load on the primary.
  • Backup copy — if the primary goes down, the replica holds the data.

On its own, a replica does not switch to primary mode on failure — for that you need Sentinel.

Sentinel: fault tolerance

Redis Sentinel is a set of watcher processes that monitor the primary and the replicas. If the primary becomes unavailable, Sentinel elects a new primary from the replicas by vote and notifies the applications.

# sentinel.conf — minimal configuration
sentinel monitor mymaster 192.168.1.10 6379 2
# "mymaster" — the cluster name
# 2 — the quorum: how many Sentinels must agree that the primary is unavailable
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000

A typical layout: 3 Sentinel nodes (an odd number for the quorum), 1 primary, 1-2 replicas. The application connects to Sentinel, which reports the current primary address.

In Spring Boot, Sentinel is configured via application.yml:

spring:
  data:
    redis:
      sentinel:
        master: mymaster
        nodes:
          - sentinel1:26379
          - sentinel2:26379
          - sentinel3:26379

Cluster: sharding

Redis Cluster is needed when there is too much data for a single server or the write load is too high. Cluster automatically distributes keys across several primary nodes — this is sharding.

Cluster divides the key space into 16384 hash slots. Each primary is responsible for a range of slots. The key user:42 is hashed into a specific slot, and Redis knows which node holds that slot.

# Minimal cluster: 3 primaries + 3 replicas (6 nodes)
# Launch via redis-cli:
redis-cli --cluster create \
  192.168.1.10:6379 192.168.1.11:6379 192.168.1.12:6379 \
  192.168.1.13:6379 192.168.1.14:6379 192.168.1.15:6379 \
  --cluster-replicas 1

In Spring Boot, a cluster is configured similarly to Sentinel:

spring:
  data:
    redis:
      cluster:
        nodes:
          - 192.168.1.10:6379
          - 192.168.1.11:6379
          - 192.168.1.12:6379

Lettuce (the default driver in Spring Data Redis) can work with a cluster transparently: it redirects requests to the right node on its own.

When to choose what:

  • A single server, restarts are not critical → no replication, RDB only.
  • You need fault tolerance → Sentinel (primary + replica).
  • The data doesn't fit on a single server → Cluster.

Monitoring and common problems

The INFO command

INFO returns detailed statistics about the server's state:

# General information
INFO

# Memory section only
INFO memory

# Replication statistics only
INFO replication

Key metrics to monitor:

  • used_memory — how much memory is used
  • connected_clients — the number of connections
  • keyspace_hits / keyspace_misses — cache hits and misses
  • rdb_last_bgsave_status — the status of the last snapshot
  • role — primary or replica

Slow commands

Redis keeps a log of slow commands. The KEYS * command is a classic example of a blocking operation: it walks through all keys and blocks the server for the duration. Use SCAN instead.

# Set the threshold in redis.conf (in microseconds, 10000 = 10 ms)
slowlog-log-slower-than 10000
slowlog-max-len 128

# View slow commands
SLOWLOG GET 10

# Iterate over keys without blocking (instead of KEYS)
SCAN 0 MATCH user:* COUNT 100

Big keys

Storing a huge value in a single key (for example, a list of a million elements) is a common problem. Such a key:

  • takes a long time to serialize when saving to RDB/AOF;
  • blocks the server during operations like DEL (deleting a large list is a synchronous operation).

To delete big keys, use UNLINK instead of DEL — it performs the deletion asynchronously in the background.

# Find big keys (the built-in scanner)
redis-cli --bigkeys

# Asynchronously delete a big key
UNLINK huge_list_key

In short

  • RDB — a snapshot to disk, fast startup, possible data loss between snapshots.
  • AOF — a command log, you lose at most a second, the file needs to be rewritten periodically.
  • maxmemory + allkeys-lru — the standard choice for a Redis cache.
  • noeviction — for a store where data must not be lost.
  • Replication gives you a backup copy and read scaling; Sentinel adds automatic failover.
  • Cluster is needed when a single node runs out of memory or write capacity.
  • KEYS * blocks the server — use SCAN; DEL of a big key also blocks — use UNLINK.
  • Redis fundamentals: data structures and the working model
  • Redis in Spring Boot: caching and RedisTemplate
  • Redis beyond caching: queues, locks, counters