MongoDB를 NUMA system에서 기본 설정으로 구동시키면 아래와 같은 식으로 WARNING이 뜬다.

[initandlisten] ** WARNING: You are running on a NUMA machine.

[initandlisten] **          We suggest launching mongod like this to avoid performance problems:

[initandlisten] **              numactl --interleave=all mongod [other options]


친절하게 어떻게 하라고까지 되어 있으니 그대로 하면 되긴 되는데 왜 그런지 궁금했다.

(사실 numactl --interleave=all 과 함께 zone_reclaim_mode도 함께 처리되어야 하지만...)


우선 NUMA가 뭐냐면 초절정 간단하게 말해서 메모리 접근의 latency를 줄이기 위해서 CPU processor마다 특정범위의 메모리를 할당해서 지역성(locality)를 부여하는 방식이다.

이렇게 묶여진 CPU와 메모리를 node라고 칭한다.


일반적인 상황에선 프로세스 하나가 메모리를 그렇게 많이 필요로 하지 않으므로 그냥저냥 잘 돌아가는데,

MongoDB를 비롯한 DB의 경우엔 하나의 프로세스가 서버의 램을 전부 먹어버릴 기세로 돌아가기 때문에 문제가 발생하게 된다.


예를 들어,

램이 64G인 서버가 2개의 node로 구성되었고 node 1개에 할당된 램이 각각 32G 씩이라고 가정했을 때,

전체 램 사용량이 53G이고 node 0의 램은 전부 사용되고 있고 node 1의 램은 좀 남은 상황이라고 하자.

이 때 어떤 프로세스가 node 0에 할당되어 있는데 메모리 할당을 요청하면,

기본설정의 NUMA에서는 node 0를 뒤적거리게 되고,

node 0의 램은 만땅 사용중이므로 새로 들어온 메모리 할당을 해주기 위해 기존에 할당되어 있던 메모리의 일부를 swap-out 해버리게 된다.

분명히 가용 메모리가 있다고 나옴에도 불구하고 미친듯이 swap-out이 일어나면서 헬게이트가 열리게 되는 것이다.

이 swap-out된 메모리가 기존에 MongoDB가 사용하고 있던 부분이라면 당연히 MongoDB가 느려지게 마련이다.


이런 사태를 막기 위해 numactl --interleave=all 로 하는데,

이건 메모리 할당을 node 하나에만 몰빵하는게 아니라 round-robin 방식으로 여러 노드에 동일하게 나눠서 할당하도록 설정해서 위에서 예로 든 상황이 일어나지 않도록 하는 것이다.



엄청 압축해서 메모한건데 자세한 내용은 아래 페이지들을 참조할 것.


[참조]

MongoDB and NUMA Hardware

http://docs.mongodb.org/manual/administration/production-notes/#mongodb-and-numa-hardware


The MySQL "swap insanity" problem and the effects of the NUMA architecture (사실 여기만 보면 된다..)

http://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/


NUMA (Non-Uniform Memory Access): An Overview

https://queue.acm.org/detail.cfm?id=2513149









Posted by bloodguy
,