Redis Latency, Evictions and Persistence: Reading INFO Like an Incident Report
Redis is single-threaded in command processing, so every symptom — a spike, an eviction, a replication gap — shows up in a handful of INFO fields. This guide maps each incident type to the fields and commands that prove it.
The 60-second triage
redis-cli INFO memory | egrep 'used_memory_human|maxmemory_human|evicted_keys|mem_fragmentation_ratio' redis-cli INFO stats | egrep 'keyspace_hits|keyspace_misses|rejected_connections|total_commands_processed' redis-cli INFO persistence | egrep 'rdb_last_bgsave_status|aof_last_write_status|loading' redis-cli INFO replication | egrep 'role|connected_slaves|master_link_status|master_repl_offset' redis-cli --latency -h <host> # live latency probe from the client side
These four blocks answer: is memory the problem, is traffic the problem, did persistence fail, and is replication healthy.
Memory pressure and evictions
evicted_keys increasing and hit rate dropping (keyspace_hits/(hits+misses)) means the dataset outgrew maxmemory and the policy is throwing keys away. With noeviction (the dangerous default for caches) writes instead fail with OOM command not allowed when used memory > 'maxmemory'.
redis-cli CONFIG GET maxmemory maxmemory-policy redis-cli INFO memory | grep evicted_keys
- For a cache:
allkeys-lru(orallkeys-lfufor skewed popularity) is usually right — evictions are the cache working, not failing; the question is whether the hit rate stays acceptable. - For a data store: never rely on eviction; size memory with headroom and alert at 80% of maxmemory.
redis-cli --bigkeys # samples the largest keys per type redis-cli OBJECT ENCODING mykey # ziplist vs hashtable matters a lot redis-cli MEMORY USAGE mykey # exact bytes for one key
Typical culprits: unbounded lists/streams (no MAXLEN), hashes that crossed the ziplist threshold into hashtable encoding, and keys with no TTL accumulating forever. A cache where "someone forgot expiry" is the most common eviction incident of all — audit with --bigkeys and redis-cli --scan | head plus TTL sampling.
Latency spikes: the single-threaded bill
Because one thread runs commands, any O(N) operation or background stall becomes everyone's latency. The built-in monitor for this:
redis-cli CONFIG SET latency-monitor-threshold 50 # log events over 50ms redis-cli LATENCY LATEST redis-cli LATENCY REPORT redis-cli --latency-history -i 1 # per-second view during the incident
The usual suspects, in order of frequency:
- Big keys:
KEYS *,SMEMBERSon million-member sets,HGETALLon huge hashes. Replace withSCAN/SSCANand paginated reads. - Fork for RDB/AOF-rewrite: on hosts with many GBs and slow memory (or oversold VMs), the fork itself stalls the event loop. Watch
latest_fork_usec; if it is in the hundreds of ms, schedule snapshots off-peak, reduce dataset size, or move to hosts with better memory bandwidth. Transparent Huge Pages amplifies this — Redis docs still recommend THP disabled. - Swap: if
mem_fragmentation_ratiois far above 1 and the host swaps, every touched page costs a disk fault. Redis should never swap; alert on host swap usage for the Redis box.
Persistence failures
| Field / error | Meaning and fix |
|---|---|
rdb_last_bgsave_status:err | Forked save failed — usually disk full or not writable; check dir free space and permissions |
aof_last_write_status:err | AOF write failed; if appendfsync always/everysec the server may stop accepting writes — free the disk, then redis-cli BGREWRITEAOF |
Slow restart, loading:1 | Loading a big RDB/AOF at boot; clients get LOADING errors — plan restarts, and monitor load time after dataset growth |
| Corrupt RDB after a crash | redis-check-rdb to inspect; restore from replica or backup; never run an unverified RDB in production |
Disk-full is the parent of most persistence incidents: an RDB snapshot needs free space comparable to the dataset while writing.
Replication problems
redis-cli -h replica INFO replication # master_link_status:down → the replica cannot keep a link: network, auth, or timeout # master_sync_in_progress:1 with a big offset → full resync in flight; expect latency on the master (fork)
- Frequent full resyncs (
repl_transferloops) mean the replication buffer (client-output-buffer-limit replica) is too small for the write rate during sync — increase it or improve the link. connected_slaveslower than expected: replicas failing auth (masterauth) show in the replica log, not the master's INFO.- Use
WAITor replica offset comparison to verify your durability assumptions after a failover drill.
Client-side errors worth memorising
| Error | Real cause |
|---|---|
LOADING Redis is loading the dataset in memory | Server still warming up after start; client retry logic needed |
READONLY You can't write against a read only instance | Client pointed at a replica, or a promoted replica's flag not cleared |
OOM command not allowed... | maxmemory hit with noeviction — see the memory section |
MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk | Background save failing; free the disk or set stop-writes-on-bgsave-error no consciously |
Prevention checklist
- Set maxmemory and an explicit policy on day one; alert on evicted_keys rate and on used_memory at 80%.
- Enable the latency monitor with a 25–50ms threshold and keep
LATENCY REPORToutput in your runbook. - Keep THP disabled on Redis hosts and watch
latest_fork_usecafter every dataset growth. - Alert on
master_link_statusand on disk free space of the persistence directory. - Ban
KEYS *in production (rename-command or ACL) and use SCAN-based tooling.