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:
| Policy | Behavior |
|---|---|
noeviction | Reject writes with an error (doesn't touch the data) |
allkeys-lru | Evict any keys on a "least recently used" basis |
volatile-lru | Evict only keys with a TTL, by LRU |
allkeys-random | Evict any keys at random |
volatile-ttl | Evict keys with the smallest remaining TTL |
volatile-random | Evict 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) →
noevictionplus 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 usedconnected_clients— the number of connectionskeyspace_hits/keyspace_misses— cache hits and missesrdb_last_bgsave_status— the status of the last snapshotrole— 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 — useSCAN;DELof a big key also blocks — useUNLINK.
What to read next
- Redis fundamentals: data structures and the working model
- Redis in Spring Boot: caching and RedisTemplate
- Redis beyond caching: queues, locks, counters