이슈상황
- Redis를 maxmemory 까지 쓰는 상황
- 지속적으로 set 커맨드가 유입되고 이로 인해 key eviction이 발생하면서 memory 단편화가 심해짐
- 이는 곧 서버 메모리 사용량 상승을 초래하고 심하면 OOME 까지도 유발할 수 있음
- Replica도 Master와 같은 데이터를 처리하기 때문에 memory fragmentation 현상도 동일하게 겪게되어 Replica도 동일하게 OOME 발생위험이 있음
- 아래 모니터링 지표는 NHN cloud의 EasyCache에서 제공하는 기능임
redis memory(rss)
서버 메모리
memory fragmentation
key eviction
set / get call
activedefrag?
Redis key를 메모리에 할당할 때 연속적인 block에 할당하게 되고 key가 삭제되면 그 공간도 비워주게됨
만약 새로 들어오는 key의 크기가 균일하지 않고 들쭉날쭉하면 비워진 block에 key를 할당할 수 없게되어 새로운 연속된 block을 찾아 key를 할당하게 됨
이런 현상이 심해지면 군데군데 이 빠진 fragmentation 이 심해져 실제 Redis memory 사용량 보다 더 많은 서버 memory를 차지하게 되는데
이러한 fragmentation을 online 중에 정리할 수 있는 기능이 activcedefrag 기능임
Redis 4.0 부터 사용가능하며 5.0부터 많이 안정화 되었다고함
발동 조건
ACTIVE-DEFRAG-IGNORE-BYTES :
- 조각모음을 시작하기 위한 최소량
- info memory에서 조회된 allocator_frag_bytes = active - allocated 값이 설정한 값보다 작으면 activedefrag 하지 않음. default 100MB
ACTIVE-DEFRAG-THRESHOLD-LOWER
- 조각모음을 시작할 최소 조각화 비율
- allocator_frag_ratio = active / allocated 값이 설정한 값보다 작으면 activedefrag 수행하지않음 default 10%
mem_allocator
- jemalloc 을 사용해야 하며 linux에서 Redis 설치 시 default임
두 조건이 모두 만족할 때 수행됨
127.0.0.1:6379> config get ACTIVE-DEFRAG-IGNORE-BYTES
1) "active-defrag-ignore-bytes"
2) "104857600"
127.0.0.1:6379> config get ACTIVE-DEFRAG-THRESHOLD-LOWER
1) "active-defrag-threshold-lower"
2) "10"
원리
- 연속된 free memory block을 만들어주기 위해 중간에 알박기 하고있는 데이터를 옆으로 이동시키고 memory block을 병합시키는 원리인듯함
효과
빨간선 -> REPLICA, activedefrag 비활성
파란선 -> MASTER, activedefrag 활성
redis memory(rss)
서버메모리
memory fragmentation
defrag 수행 전 / 후 지표
수행 전
OS CPU / 메모리
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13119 redis 20 0 9570612 6.358g 1380 S 0.0 83.2 1969:27 redis-server
redis info
# Memory
used_memory_human:5.38G
used_memory_rss_human:6.33G
used_memory_peak_human:5.39G
allocator_allocated:5782084072
allocator_active:6677209088
total_system_memory_human:7.64G
maxmemory_human:5.38G
allocator_frag_bytes:922989456
allocator_frag_ratio:1.15
mem_fragmentation_ratio:1.18
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
# Stats
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
- 실제 Redis 메모리 사용량은 used_memory_human:5.38G
- mem_fragmentation_ratio:1.18 에 달해 서버 메모리 used_memory_rss_human:6.33G 까지 쓰고있는 상황
- 정리 대상 fragmentation data 크기는 allocator_frag_bytes:922989456, 900MB정도
- allocator_frag_ratio:1.15 비율은 10%를 넘긴 상황
- 발동조건이 만족되었기 때문에 activedefrag yes로 설정 시 activedefrag 기능이 바로 수행될 것임
수행 중
activedefrag yes
127.0.0.1:6379> redisconfig set activedefrag yes
OK
OS CPU / 메모리
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13119 redis 20 0 9570612 6.359g 1408 S 8.8 83.2 1969:28 redis-server
redis info
# Memory
used_memory_human:5.39G
used_memory_rss_human:5.79G
used_memory_peak_human:5.39G
allocator_allocated:5785638544
allocator_active:6075428864
total_system_memory_human:7.64G
maxmemory_human:5.38G
allocator_frag_ratio:1.05
mem_fragmentation_ratio:1.07
mem_allocator:jemalloc-5.1.0
active_defrag_running:9
- active_defrag_running : 9 , active_defrag가 돌면서 메모리도 많이 정리되는 중임
- activedefrag 돌면서 CPU는 조금 쓰는 모습
수행 후
OS CPU / 메모리
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13119 redis 20 0 9570612 6.359g 1408 S 1.1 72.9 1969:28 redis-server
redis info
# Memory
used_memory_human:5.38G
used_memory_rss_human:5.55G
used_memory_peak_human:5.39G
allocator_allocated:5781963352
allocator_active:5837156352
total_system_memory_human:7.64G
maxmemory_human:5.38G
allocator_frag_bytes:83108768
allocator_frag_ratio:1.01
mem_fragmentation_ratio:1.03
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
# Stats
active_defrag_hits:5134002
active_defrag_misses:23330219
active_defrag_key_hits:2994915
active_defrag_key_misses:3473898
정리
- 메모리 단편화가 심할 때 activedefarg 켜주면 효과가 정말 좋음
- 메모리 빡빡하게 쓰는 서비스는 항시 켜놓는 것이 좋을듯
- 운영 중 set / get 커맨드가 많이 들어오는 환경에서도 서비스에 이슈 없음
- defrag 정리 중 CPU만 조금 쓰는데 미비한 수준, CPU limit 관련 설정도 있는데 굳이 건드릴 필요 없을듯
- 정확히 시간은 체크 못했으나 6.33G -> 5.55G 약 1GB 정리하는데 10분안쪽으로 소요된듯
- maxmemory 를 해소하는 건 아님!! maxmeomry 는 별개로 redis 스펙업 해줘야함, activedefrag는 단편화 해소하는 기능
- 관련 설정은 http://redisgate.kr/redis/server/redis_conf_han.php 참고