MongoDB의 분산 락

Pinterest

글 : 이승용

MongoDB는 mongos들간의 config 서버와의 데이터 통신 동기화를 위해 분산 락 개념을 도입하고 있다. 락lock이란 쓰레드 또는 프로세스들 간에 공유자원을 확보하기 위한 수단으로 누군가가 사용하고자 하는 자원을 독점하고 있다면, 다른 이들은 해당 자원을 사용할 수 없다.[1] MongoDB의 분산 락 역시 일반 락과 동일하게, mongos가 사용하게 되는 자원의 독점을 위해 분산 락을 사용한다. Mongos가 독점하는 자원은 다음과 같다.

  • 밸런서balancer의 연산
  • 컬렉션collection의 분할split
  • 컬렉션의 이관migration

상기의 내용을 보면 공유자원이기 보다는 연산 쪽에 가깝다. 맞다. Mongos는 mongos의 핵심 기능인 샤딩을 수행할 연산들에 대해 분산 락을 사용한다. 즉, 여러 개의 mongos가 설치되어 있다면, 설치된 mongos 중에 상기의 작업을 아무나 먼저 시작할 수 있고, 시작된 연산에 대해 독점하고 있음을 다른 mongos에 알려주어야 한다. 독점 여부를 알려주는 방법이 분산 락이다. [그림 4-11]은 mongos와 config 서버와의 분산 락 구조를 보여준다.

 

[그림 4-11]

 

[그림 4-11]에서 mongos의 시작과 함께 분산 락을 모니터링하기 위한 LockPinger 쓰레드가 생성된다. LockPinger 쓰레드는 30초 주기로 config 서버와 통신하며, 주요 업무는 다음과 같다.

  • 30초 주기로 ping 타임을 갱신한다.
  • 4일 지난 ping 데이터를 삭제한다. 따라서 4일 동안의 ping 데이터만 보관한다.
  • Unlock된 분산 락 정보를 초기화한다.

LockPinger 쓰레드의 중요한 역할은 30초 주기로 ping 타임을 갱신하는 것이다. 이 ping 타임은 분산 락 지속시간과 관련 있다. 예를 들어, 분산 락 지속시간이 일정 시간을 초과하였지만, ping 타임이 30초 주기로 계속 갱신을 하고 있다면, 시스템 부하가 발생한 것이 아니라, 분락 락을 이용한 연산이 오래 걸린다고 판단할 수 있다. 반대로, 분산 락 지속시간과 ping 타임이 동일하게 변하기 않고 있다면, 분산 락을 소유한 노드에 문제가 발생한 것으로 판단할 수 있다.

그럼, mongos가 분산 락을 어떻게 처리하는 지 흐름을 파악해 보자. [그림 4-11]과 같이 MongoDB는 분산 락을 특정 이름으로 구성한다. Mongos가 사용하는 분산 락의 이름은 balancer라는 고정된 분산 락과 컬렉션 명으로 구성된 분산 락 이름이 사용된다. Mongos에서 특정 이름의 분산 락을 확보하기 위해 lock_try()라는 함수를 호출한다. 함수 lock_try()는 primary로[2] 설정된 첫 번째 config 서버에 해당 이름의 락이 설정되어 있는지 요청한다. 왜 첫 번째 config 서버에서만 락 정보를 얻어오는가? MongoDB는 SyncCluster라는 개념의 연결 풀connection pool을 사용한다. SyncCluster는 n개의 서버와 동시에 연결되어 있으며, 쓰기 연산에 대해서는 n개의 서버에 동시에 데이터를 전달하고, 읽기 연산에 대해서는 n개 중 한 개의 응답만 전달되면 값을 리턴해 준다. Config 서버는 3대 모두 항상 죽어서는 안 되는 구조이기 때문에 읽기 연산인 분산 락 정보를 취득하는 것은 첫 번째 서버에서만 얻어오게 된다.

mongos는 취득한 분산 락 정보에 대한 결과를 분석한다. 우선, 락 정보가 존재하지 않다면, 다른 mongos에서도 한번도 획득한 적이 없는 최초의 분산 락이므로, 락 정보를 생성하고 분산 락을 취득했음을 config 서버에 통보한다. Config 서버로부터 받아온 분산 락 정보가 있다면, mongos는 분산 락 상태 플래그를 조사한다. 분산 락 상태 플래그는 0 값을 가질 경우, unlock 되었다는 것을 의미하고, 0이 아닌 값은 누군가에 의해 해당 분산 락이 lock 되었음을 의미한다. 해당 분산 락의 취득 시간과 ping 타임을 비교하여 15분을 초과하였을 경우는 분산 락을 취득한 시스템에 문제가 발생하였다고 판단하고 락을 강제로 해제하고 새로운 소유자가 소유되었음을 통보한다. 분산 락의 활용이 완료되었다면, mongos는 unlock() 함수를 통해 해당 분산 락의 상태 플래그를 0으로 변환하고, 분산 락이 해제되었음을 config 서버에 통보한다.

이 부분에서 우리는 한가지 의문점이 생긴다. 즉, 두 개의 mongos에서 동시에 동일한 분산 락을 획득하기 위해 시도할 경우에는 어떻게 될 것인가? 다행스럽게도 MongoDB는 앞 절에서 살펴보았듯이 쓰기 연산은 락이 전역적으로 한 개만 존재하며, mongos는 config 서버와의 쓰기 모드를 SAFE로 처리하기 때문에 쓰기에 관한 트랜젝션transaction은 보호된다. 다만, [그림 4-11]에서 락을 취득하기 위해서는 락 요청과 락 취득 이라는 2단계 작업이 수행되는데, 락 요청과 취득 사이에 다른 mongos에서 분산 락을 취득할 수 있다. 이러한 문제를 위해 mongos는 분산 락 취득 후, 다시 분산 락 정보는 요청하여 소유자가 자신과 동일한지 판단하고, 동일하다면 성공 아니면 실패로 간주한다.

 

이전글 : mongos와 응용

다음글 : MongoDB의 샤딩 한계

 


[1] 공유 자원은 메모리, 디스크, CPU 등 컴퓨터상에 존재할 수 있는 하드웨어들을 말한다.

[2] Mongos를 기동시킬 때, 지정된 첫 번째 config 서버가 primary 서버가 된다.


  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS
  1. 아직 댓글이 없습니다.
  1. 엮인글들이 아직 없습니다.