The MAXMEMORY noeviction policy in Redis is failing to block writes because a background eviction process is still running, preventing new data from being written.
Here’s a breakdown of why this happens and how to fix it:
1. The Real Culprit: maxmemory-samples
- Diagnosis: The most common reason
noevictionseems to fail is that Redis, by default, doesn’t check every key whenmaxmemoryis hit. Instead, it samples a small number of keys (maxmemory-samples, default 5) to decide if eviction is needed. If the sampled keys are not eligible for eviction (e.g., they are recent or have no TTL), Redis might continue accepting writes even if the memory limit is technically exceeded, leading to a crash. - Fix: Increase
maxmemory-samplesto a higher value. A common recommendation ismaxmemory-samples 10. - Why it works: A larger sample size increases the probability that Redis will find keys eligible for eviction when the memory limit is approached, thus triggering the eviction process more reliably before memory runs out completely.
- Command: Edit your
redis.conffile and add or modify the line:
Then, restart your Redis instance.maxmemory-samples 10
2. The maxmemory Limit Itself is Too High (Relative to Available RAM)
- Diagnosis: You’ve set
maxmemoryvery close to your server’s total RAM, leaving no buffer for Redis’s internal data structures, operating system overhead, or other processes. When Redis tries to evict, it needs a small amount of temporary memory to do so, and if there’s no headroom, even eviction can fail. - Fix: Lower your
maxmemorysetting. If your server has 4GB RAM, don’t setmaxmemoryto 3.9GB. Aim formaxmemory 3GBormaxmemory 3.5GBto leave breathing room. - Why it works: Providing a buffer ensures that Redis can perform its eviction operations without immediately hitting an out-of-memory condition itself, allowing the
noevictionpolicy to eventually block writes. - Command: Edit your
redis.conffile and set:
(Replacemaxmemory 3GB3GBwith an appropriate value based on your server’s total RAM). Restart Redis.
3. Eviction Strategy Mismatch
- Diagnosis: While
noevictionis selected, the underlying eviction mechanism might be inefficient for your data. If you have many keys without TTLs, Redis has nothing to evict.noevictionmeans "don’t evict anything," but it assumes that if memory is full, it can evict if it were configured to do so. If there’s truly nothing to evict, it will eventually fail. - Fix: Temporarily switch to an eviction policy that can evict, like
allkeys-lru, to clear out memory. Then, re-evaluate your data strategy. If you neednoeviction, you must have keys with TTLs or a plan to manage memory proactively. - Why it works:
allkeys-lruwill aggressively remove the least recently used keys, making space. This is a temporary measure to get Redis back online; it doesn’t solve the long-termnoevictionproblem if your data model doesn’t support it. - Command: In
redis-cli:
After memory is freed, you can then decide ifCONFIG SET maxmemory-policy allkeys-lrunoevictionis truly appropriate or if you need a different strategy. If you must usenoeviction, ensure you have TTLs on your keys.
4. Background Save/AOF Rewrite Interference
- Diagnosis: Redis performs background operations like RDB saves (
BGSAVE) and AOF rewrites (BGREWRITEAOF). These operations fork the main Redis process, which can temporarily double the memory usage. If you’re already at yourmaxmemorylimit, this fork can exhaust available RAM and cause the parent process to crash. - Fix: Temporarily disable or postpone background saves/rewrites when you anticipate hitting
maxmemory. You can also configurestop-writes-on-bgsave-error yesinredis.confto make Redis explicitly stop writes during aBGSAVEif it fails due to memory pressure. - Why it works: Preventing or explicitly halting operations that consume significant extra memory during critical memory states allows Redis to manage its primary write/read operations and eviction attempts more gracefully.
- Command:
- To disable RDB snapshots (not recommended long-term): Edit
redis.conf, comment out thesavelines. - To disable AOF (not recommended long-term): Edit
redis.conf, setappendonly no. - To ensure writes stop on save errors: Edit
redis.confand add:stop-writes-on-bgsave-error yes
- To disable RDB snapshots (not recommended long-term): Edit
5. maxmemory-policy not actually set to noeviction
- Diagnosis: It sounds basic, but sometimes the configuration isn’t applied correctly or was reverted. You might think it’s set to
noeviction, but it’s actually using a different policy that is evicting, or worse, a policy that also doesn’t evict but has other issues. - Fix: Explicitly set the policy.
- Why it works: Ensures the intended policy is active.
- Command: In
redis-cli:
You can verify withCONFIG SET maxmemory-policy noevictionCONFIG GET maxmemory-policy.
6. External Memory Pressure
- Diagnosis: The
maxmemorysetting in Redis only controls Redis’s own memory usage. The operating system and other processes on the server might be consuming significant RAM. If the OS starts swapping, Redis performance degrades drastically, and it might appear to be blocking writes due to memory pressure even if its internalmaxmemorylimit hasn’t been strictly breached yet. - Fix: Monitor overall system memory usage. Reduce memory consumption by other processes, or add more RAM to the server. Ensure
vm.swappinessis set appropriately (e.g.,10or20on production systems) to discourage swapping. - Why it works: By ensuring the OS has sufficient memory and is not swapping, Redis can operate within its configured limits without external interference.
- Command: Check system memory with
free -handtop. Adjust swappiness:
To make it permanent, editsudo sysctl vm.swappiness=10/etc/sysctl.conf.
After applying these fixes, you should find that Redis correctly blocks writes when maxmemory is reached under the noeviction policy. The next error you’ll encounter is likely related to the specific operation that’s failing due to the block, such as OOM command not allowed when used memory > 'maxmemory'.