Memory fragmentation rate formula

mem_fragmentation_ratio = used_memory_rss/used_memory
Copy the code
  • Used_memory: Specifies the memory space allocated using the allocator of the Redis service.
  • Used_memory_rss: specifies the memory size allocated by the operating system to the Redis instance, which indicates the physical memory size occupied by the process.

The USed_memory_RSS metric also includes the overhead of memory fragmentation, which is caused by inefficient allocation/reclaiming of physical memory by the operating system.

  • Mem_fragmentation_ratio < 1: Indicates that the Redis memory allocation exceeds the physical memory. The OPERATING system is swapping memory. Memory swapping causes a significant response delay.
  • Mem_fragmentation_ratio > 1: is reasonable;
  • Mem_fragmentation_ratio > 1.5: Indicates that Redis consumes more than 150% of the actual required physical memory. 50% of the memory fragmentation rate may be a result of the memory management deterioration in the operating system or Redis instance.

Cause of high memory fragmentation rate

  • In case of variable-length key-value load: the stored data varies greatly in length and is frequently updated. Each K-V of Redis is the most suitable for the initialized memory size. When the modified value changes and the original memory size is not applicable, the memory needs to be reallocated. After the reallocation, redis will not be able to recycle some of the memory, has been occupied.
  • The maxMemory limit caused the key to be reclaimed and deleted
  • Redis writes a large amount of data, and the key of the data is inconsistent with the original data. When the data exceeds the maxMemory limit, Redis will eliminate part of the old data through the key reclamation strategy. However, the memory occupied by the obsolete data is not released by the Redis process. As a result, the valid data in Redis memory does not exceed the maximum memory, but the memory of the entire process keeps growing.
  • The evicted_keys field in the info information shows the number of keys that were reclaimed and deleted due to maxMemory limitations.
  • The frequent reclaiming of keys increases the delay of client command response, because Redis not only has to process the command request from the client, but also frequently reclaims the key that meets the condition.

The solution

  • Limit swapping: If the memory fragmentation rate is less than 1, Redis instances may swap some of their data to disk. You should increase the available physical memory or reduce the actual Redis memory footprint. Setting maxMemory and reclamation policies can avoid forced swapping.

  • Restart the Redis server: If the memory fragmentation rate exceeds 1.5, restarting the Redis server disables additional generated memory fragments and reuses them as new memory, allowing the operating system to resume efficient memory management.

  • The extra fragmentation occurs because Redis freed the memory block, but the memory allocator did not return the memory to the operating system.

  • Defragmentation: Redis 4.0-RC3 later supports defragmentation using Jemalloc as the memory allocator (the default) and automatic defragmentation at run time.

    • Activedefrag Yes Enables automatic memory defragmentation (main switch) : sets automatic defragmentationconfig set activedefrag yes, the use ofconfig rewriteRefreshes the new configuration in Redis memory to the configuration file.
    • After Redis4.0, you can use the new instruction to manually reclaim memory fragmentation, and the configuration monitoring usage performance is better.
      • Support for manual cleanup with the Memory Purge command (as opposed to automatically clearing areas)

If you look at the current memory fragmentation rate, the mem_fragmentation_ratio is high: 1.54, which means 54% of the memory is wasted

$redis-cli -p 6383 info memory # memory used_memory:1073741736 used_memory_human:1024.00M used_memory_rss:1650737152 Used_memory_rss_human: 1.54 G used_memory_peak: 1608721680 used_memory_peak_human: 1.50 G used_memory_peak_perc: 66.75% Used_memory_overhead: 253906398 used_memory_startup: 766152 used_memory_dataset: 819835338 used_memory_dataset_perc: 76.41% Total_system_memory: 67535904768 total_system_memory_human: 62.90 G used_memory_lua: 37888 used_memory_lua_human: 37.00 K Maxmemory: 1073741824 maxmemory_human: 1.00 G maxmemory_policy: allkeys - lru mem_fragmentation_ratio: 1.54 Lazyfree_pending_objects mem_allocator: jemalloc - 4.0.3 active_defrag_running: 0:0Copy the code

Enable automatic memory defragmentation

$ redis-cli -p 6383 config set activedefrag yes
OK
$ redis-cli -p 6383 config rewrite
Copy the code

Perform manual cleaning

$ redis-cli -p 6383 memory purge
Copy the code

The actual case

Concurrent scenarios:

  • Up to 1600W times a day to write hmSET, and the length of the value is different (validity: 24 hours);
  • The key corresponding to the above hmset write operation is different every day;

Common scenarios:

  • High write load, especially for batch delete operations.
  • The stored K-V values vary greatly in length.

Comprehensive solution:

  • There is no practical solution better than a restart.
  • The memory size can be expanded conditionally.
  • Add memory monitoring and restart Redis to reclaim memory when the memory usage reaches the threshold

The pr has been submitted on January 1, 2017, related address: github.com/antirez/red…

Configuration description:

# fragmentation # activedefrag yes # Minimum amount of fragmentation waste to start active Active -defrag-ignore-bytes 100mb # Minimum percentage of fragmentation to start active defrag # Active -defrag-threshold-lower 10 # Maximum percentage of fragmentation at which we use Maximum effort # Active-defrag -threshold-upper 100 # Minimal effort for defrag in CPU percentage active-defrag-cycle-min 25 # Maximal effort for defrag in CPU percentage active-defrag-cycle-max 75Copy the code