들어가며
Redis 오픈소스는 Remote Dictionary Server의 약어로, 전세계적으로 널리 사용되고 있는 In-memory cache 솔루션이다. 또한, Redis는 다양한 데이터 구조 집합을 제공하고 있다. DB-Engines Ranking of Key-value Stores에 따르면, Redis는 현재 가장 인기 있는 key-value store로써, BSD 라이선스를 보유하고 최적화된 C언어 코드로 작성되어 있으며, 다양한 개발 언어를 지원하고 있다. 주요 Redis 사용 사례는 caching, 세션 관리, pub/sub, 순위표 등이 있다.
Redis는 영구적으로 저장하는 AOF/RDB 방식의 Redis DB백업용도로 사용되고 있으며, 주로 In-memory cache 다 보니 저장 cache 용도로 많이 사용되고 있다. Redis는 시스템 성능을 높이는데 많은 역할을 하는 좋은 솔루션이지만, Redis라는 솔루션은 메모리 측면에서 제대로 관리하지 않으면 장애로 이어지기도 한다. Redis는 메모리에 데이터를 저장하기 때문에 물리메모리(RAM) 용량보다 더 많은 데이터를 사용하게 될 경우 메모리 부족으로 인해 swap이 발생하여 Redis의 성능 저하를 일으킬 수 있다.
위의 [그림2]와 같이 데이터를 물리 메모리의 용량보다 더 많이 사용하게 되면, swap이 발생하는 것을 볼 수가 있으며, 운영체제에서 Swap space의 주요 기능은 물리메모리(RAM)의 양이 가득 차고 더 많은 메모리의 양이 필요할 때 Backing store(디스크)의 가상메모리에 대체하게 된다.
Redis는 메모리에 데이터를 저장하고 있어서, 메모리 한계상 메모리 용량 보다 데이터를 더 많이 사용하게 되면, 메모리 이슈가 발생할 수 있다. 그래서, 운영체제(OS)에서 swap의 설정에 따른 메모리 이슈에 대해 2가지 사례를 소개하겠다.
[이슈 사례1]
Swap 메모리 설정 시, 실제 메모리가 부족하더라도 시스템다운 및 프로세스 멈춘현상(Hang)을 방지할 수 있어 보다 안정적일 수 있지만, 디스크의 공간을 메모리처럼 사용하게 되어 처리 속도가 떨어져 성능 저하로 이어질 수 있다.
[이슈 사례2]
Swap이 없는 상태에서 Redis 서버가 maxmemory 양 보다 더 많은 데이터를 사용한 경우, Redis가 “Redis: OOM(Out of memory) command not allowed when used memory than ‘maxmemory’” 에러를 일으킬 수 있다.
IT 개발자, 클라우드 엔지니어, 운영자 관리자는 성능을 높이기 위해 Redis 오픈소스를 cache용도로 도입하면 메모리 측면의 예기치 못한 이슈들이 발생한다. 이러한 이슈들은 하드웨어 스펙과 비즈니스 프로세스에 맞게 적합한 아키텍처를 적용하여 해결할 수 있다.
본 아티클에서는 IT 개발자, 클라우드 엔지니어, 운영자 관리자가 고려해야 할 Redis의 메모리 할당 및 관리 방안에 대해 살펴보겠다.
그렇다면, Redis는 메모리에 대해 어떻게 관리할까?
Redis는 이러한 메모리 관리를 위해 “maxmemory” 옵션 설정을 통해 메모리의 양을 그 이상의 범위를 사용하지 않도록 제한할 수 있다. 그리고, Redis는 인 메모리 데이터 저장소로 사용하며 일반적인 디스크 솔루션에 비해 적은 양의 데이터를 저장함으로써, 이로 인해 최대치로 저장하게 되면 Redis 메모리에 새로운 데이터가 들어오게 되고, 기존의 데이터는 제거되는 방식으로 작동되어야 한다. 이것을 eviction이라고 부르는데, 이러한 방식을 만들기 위해 “maxmemory-policy”옵션을 통해 eviction 정책을 만들 수 있다.
[2.1 Maxmemory configuration]
Maxmemory configuration은 설정된 메모리의 양까지 사용하도록 Redis를 구성하는 것이다. 이는redis.conf 파일에서 설정할 수 있고, 런타임 시 CONFIG SET 명령을 사용하여 maxmemory의 양을 지정할 수 있다.
예) 메모리 제한을 100MB로 구성하려면 redis.conf 파일 내에서 다음과 같이 설정할 수 있다.
maxmemory를 0으로 설정하면, 메모리 제한이 없습니다. 이는 64비트 시스템의 기본 동작이며, 32비트 시스템은 3GB의 메모리 제한을 사용합니다. 즉, 64비트 시스템에서는 메모리 제한이 없다는 것입니다. 그래서, swap 영역까지 사용하지 않도록 Redis 설정에서 메모리 용량을 제한해야 하며, redis.config 파일 내에 maxmemory 옵션 설정 값으로 지정할 수 있다.
[2.2: maxmemory-policy configuration]
Maxmemory 제한에 도달했을 때 Redis가 따르는 eviction의 정확한 동작은 maxmemory-policy 정책에 따라 작동한다. Redis에서 Eviction을 위해 사용하는 방식 중에 가장 일반적으로 사용되고 있는 LRU(Least Recently Used)알고리즘 입니다. LRU 알고리즘은 보통 운영체제(OS)에서 페이지 교체 알고리즘으로 사용되고 있다.
운영체제(OS)에서 페이지 교체 알고리즘
다음은 운영체제(OS)에서 사용되는 페이지 교체 알고리즘은 다음과 같다.
Redis에서 적용된 페이지 교체 알고리즘
운영체제(OS)의 페이지 교체 알고리즘 중 Redis에서 사용되고 있는 알고리즘은 LRU, LFU, RANDOM의 3가지를 제공한다.
Redis의 Eviction 정책은 다음과 같다.
Redis key eviction 프로세는 어떻게 작동될까?
Redis evictrion 프로세스 작업은 다음과 같이 진행된다.
- 클라이언트가 새로운 command을 실행하여, 더 많은 데이터가 추가 된다.
- Redis는 메모리 사용량을 확인하고, 설정된 maxmemory 값보다 크면 정책에 따라 keys를 evict하게 된다.
- 새로운 command가 실행된다
Redis가 메모리를 회수하는 동안 write 증폭 문제가 발생할 수 있다.
Redis의 eviction 작동 방식에서, maxmemory 제한이 설정되고 maxmemory-policy가 “noeviction”이 아닌 경우, Redis 메모리 회수 프로세스는 클라이언트가 새로운 command를 실행할 때마다 트리거된다.
예) Redis 서버가 항상 메모리 오버플로우 상태 (used_memory > maxmemory)에서 작동하는 경우 메커니즘을 자주 트리거할 것이고, 서버 성능에 영향을 미칠 수 가 있다. 또한, Replicas가 연결된 경우, key 제거 작업이 replica 노드와 동기화되어 write 증폭 문제가 발생 가능하다.
따라서, 항상 maxmemory > used_memory 상태로 Redis 서버가 실행되도록 구성하는 것이 좋다.
3-1. Redis에서는 광범위하게 다루고 있는 Approximated LRU algorithm
Redis LRU 및 LFU eviction 정책은 근사값이라는 점에 유의해야 한다.
Redis에서의 LRU 알고리즘은 정확하게 구현되어 있지 않다. 즉, Redis가 eviction을 위해 가장 오랫동안 사용되지 않은 최상위 후보를 선택할 수 없음을 의미한다.
대신에, 소수의 keys를 샘플링하고, 샘플링된 key 중에서 가장 좋은(가장 오래된 엑세스 Time을 가진) key를 eviction하기 위해 LRU approximation 알고리즘을 실행할 것 이다.
Redis 3.0부터 알고리즘은 더 좋은 eviction 후보풀을 얻기 위해 개선되었다. 이로 인해 알고리즘의 성능이 향상되어 실제 LRU 알고리즘의 동작에 더 근사할 수 있게 되었다.
Redis에서는 maxmemory-samples 파라미터 설정에서 지정한 수의 key로 샘플링하여 LRU 알고리즘의 근사치를 계산할 수 있다. 샘플 수가 많을수록 메모리는 많이 사용되지만 정밀도가 올라가는 특징이 있다.
다음과 같이 해당 파라미터는 redis.conf에서 조정할 수 있다.
Redis가 실제 LRU를 사용하지 않는 이유는 더 많은 메모리가 필요하고 CPU 사용량이 증가하기 때문이다.
아래의 그림은 Redis에서 사용하는 LRU approximation과 실제 LRU를 비교한 것이다.
위의 그래프에서 Redis는 실제 LRU와 근사치 LRU로 구분되어 있는데, Redis 3.0에서는 eviction을 위한 best candidates을 선택하는 알고리즘이 개선되면서, 실제 LRU 알고리즘과 더 유사해졌다. Redis 3.0에서 샘플링 수를 10으로 설정하면 좀 더 실제에 가까운 LRU 기능과 유사해질 수 있다.
단, 샘플 개수를 늘리면 실제 LRU 알고리즘과 더 유사해진다. 하지만 적정 수준 이상으로 샘플 개수를 설정하면 Redis의 CPU 사용량이 늘어나고 응답 속도가 늦어지는 리스크가 있다는 점을 고려해야 할 것이다.
마치며
지금까지 Redis의 메모리 설정 관리와 used_memory가 maxmemory 용량 보다 크면 eviction이 어떻게 처리되는지에 대해 살펴보았다.
IT 개발자, 클라우드 엔지니어, IT 운영자는 Redis를 사용하여 서비스로 운영한다면 가장 중요하게 고려할 부분은 메모리 측면이다. Redis에서 메모리 부족은 크리티컬한 문제로 초래할 수 있으며, 메모리 부족한 상태에 대비해서 maxmemory-policy 옵션을 통해 eviction 정책에 설정할 수 있다.
Eviction 정책을 효과적으로 설정하기 위해 Redis에서는 “Noeviction”으로 메모리를 주기적으로 모니터링해서 증설할 수 있고, 일정 기간 동안만 데이터를 유지한다면 “volatile-“로, 그렇지않으면 “allkeys-“으로 정책을 고려할 수 있다.
따라서, 시스템에서는 비즈니스 로직에 맞는 최적의 메모리 관리에 대해 어떻게 관리할 것인지 면밀히 검토한 후 결정해야 한다. IT 개발자, 클라우드 엔지니어, 운영 관리자는 앞서 소개한 아티클의 내용을 참고하여 운영환경에 도움이 되기를 바라겠다.
# References
- https://redis.io/docs/about/
- https://db-engines.com/en/ranking/key-value+store
- https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/8_MainMemory.html
- https://aws.amazon.com/ko/premiumsupport/knowledge-center/oom-command-not-allowed-redis/
- https://en.wikipedia.org/wiki/Page_replacement_algorithm
- (한국어판)Operating System Concepts, Seventh Edition, Abraham Silberschatz, John Wiley & Sons, 2008
- https://github.com/redis/redis
- https://redis.io/docs/management/optimization/memory-optimization/
- https://redis.io/docs/reference/eviction/
김남욱 프로
소프트웨어사업부 OSS사업팀
클라우드 및 오픈소스 SW 관련 연구 개발 프로젝트를 수행하였으며, 현재 OSS 기술서비스 및 아키텍처를 담당하고 있습니다.
Register for Download Contents
- 이메일 주소를 제출해 주시면 콘텐츠를 다운로드 받을 수 있으며, 자동으로 뉴스레터 신청 서비스에 가입됩니다.
- 뉴스레터 서비스 가입 거부 시 콘텐츠 다운로드 서비스가 제한될 수 있습니다.
- 파일 다운로드가 되지 않을 경우 s-core_mktg@samsung.com으로 문의해주십시오.