[발 번역] 잘가~~ Global Lock, MongoDB 2.0 vs 2.2

해당 글은 http://blog.serverdensity.com/2012/05/23/goodbye-global-lock-mongodb-2-0-vs-2-2/ 발 번역한 것입니다. 예전에 MongoDB의 Global Lock에 대해서 올라온 글(http://blog.pythonisito.com/2011/12/mongodbs-write-lock.html) 을 보면 MongoDB의 Global Lock이 성능에 어떤 영향을 주는 지 알 수 있습니다. 특히 메모리 사이즈 이상의 데이터가 올라갔을 때, 느려지는 원인 중에 이 Global Lock의 영향도 있었습니다.  그리고 2.2에서 다시 개선이 있다고 합니다. 제목만 보면 아시겠죠? 오역에 주의하시길 바랍니다.

아마도 MongoDB 에서 가장 악명 높고 자주 거론되는 문제가 Global Lock 이슈일껍니다.  Write 동작이 일어날때 전체 서버가 락이 된다는 것을 의미합니다. 엄청 안좋게 들리지만, 실제로,  성능에 끼치는 영향은 별로 없습니다. MongoDB 2.0 버전부터 이런 종류의 작업 동안 적절히 락을 포기하도록 개선이 있었기 때문입니다.(MongoDB 2.0 includes significant improvements)

확실히, MongoDB 1.8 에서는 데이터를 저장하기 전에 Memcached를 이용해서 insert를 조절했지만, 2.0으로 업그레이드 한 후에는 직접 MongoDB로 저장하고 이런 부분을 제거했습니다. 이 부분의 향상은 some benchmarks at the end of last year comparing v1.8 to 2.0 에서 잘 설명되어 있습니다.(역자 주: 제가 예전에 올린 발번역 글 중에도 해당 글이 있습니다. https://charsyam.wordpress.com/2012/01/04/%EB%B0%9C-%EB%B2%88%EC%97%AD-mongodb-write-lock/ )

FaultingWrites

그럼에도 불구하고, 2.2 버전의 중요 이슈는 Global Lock의 제거와 데이터베이스 Lock을 collection 수준의 Lock으로 변경하고 더 미래에는 더욱 더 세분화된 동시성  제어 방식으로 변경하는 것입니다.(역자 주: 일반적인 DBMS는 Global Lock(서버락), 데이터베이스 Lock, Table(collection) Lock, Page Lock, Record Lock 수준으로 볼 수 있습니다. 후자일 수록 Lock의 범위가 적습니다.)

2.2 버전에서의 개선 부분은 2 가지 입니다.

  • global reader/writer lock 의 제거 – 첫 시도로 database level lock
  • PageFaultException 구조 – page fault 시에 Lock 양보.

첫째로, database level Lcok으 구현된건 맞지만, 제대로 사용하기 위해서는 어플리케이션에서 몇가지 아키텍처 변경이 필요합니다. 예를 들어, 하나의 큰 collection을 사용하면,  하나의 커다란 database를 사용한느 것이기 때문에, 거의 차이가 없습니다. 하지만,  두번째, 동시성 향상의 경우(Lock 양보 정책) 하나의 collection 에서도 업그레이드만 하면 바로 이득을 볼 수 있을 듯 합니다.

10gen 의 CEO이자 MongoDB의 최초 개발자인 Dwight Merriman는 MongoSF에서 MongoDB의 변화와 구조에 대해서 좋은 얘기들을 많이 했습니다. 다음 .비디오를 보시길 추천합니다.

10gen 에서는 실제 사용과는 관련이 없다는 이유로, 공식 벤치마크는 제공하지 않습니다. 개인적으로 업그레이드 후에 영향받는 쿼리등을 확인하기 위해서는 benchRun 같은 도구를 이용해야 합니다.  버전에 따른 이런 차이점을 확인하는데는 벤치마크가 유용합니다.

Rick Copeland 는 꽤 멋진 벤치마크를 했고 이것은 1.8과 2.0 사이의 향상ㅇ 대해서 보여주고 있습니다. 그래서 1.8, 2.0과 대비해서 2.1를 테스트 하기로 했습니다. 2.1은 2.2 버전을 위한 개발 버전입니다.

Comparing v1.8, v2.0 and v2.1

Rick이 사용했던 Amazon EC2(m1.large)에 같은 AMI를 이용해서 완전히 동일한 코드를 사용했습니다.  같은 데이터베이스를 설치하고 Page Fault Read/Write에 대해서 벤치마크를 수행했습니다. Non Page Fault 상황은 하지 않았는데, 2.2의 주요 변경이 Page Fault 와 Locks 을 어떻게 다루는가였고, Non Page Fault는 큰 차이가 없었습니다. 그건 항상 빠르기 때문입니다.

그리고 MongoDB 가 큰 데이터를 가지고 있다고 가정했습니다. 보통, 모든 데이터와 인덱스가 메모리에 있는 상황이 아니라 워킹셋만 메모리에 존재할 것이기 때문입니다.(역자 주: 모든 데이터가 메모리에 있으면, Non Page Fault 상황이라고 봐도 크게 무방할 듯 합니다.)

MongoDB Faulting Ops/s

위의 그래프에서 확실하게 Rick의 결과를 재현했습니다. 그리고 MongoDB 2.1의 테스트 결과를 보면, 그 차이가 매우 확연합니다.  read 중에 write에 실패하는 수에 상관없이 성능이 확 떨어지는 부분이 없습니다. 이것은 global lock이 확실하게 사라졌기 때문입니다. 아래의 그래프를 봅시다.

MongoDB Faulting Lock

Rick의 도구도 이용했고, 추가로 mongod에서 무슨 일이 일어났는지 확인하기 위해서 mongostat을 이용해서 통계를 모았습니다.  확실히 global lock 에 사용된 시간은 0% 입니다.

Conclusions

많은 데이터베이스를 사용할 때 큰 성능을 주기 위해서 MongoDB 2.2에서 global lock은 사라졌습니다. 그러나 실제로 업그레이드 할만한 영향을 미치는 것을 PageFaultException 개선을 통한 Lock 양보 작업입니다.  이것은 MongoDB가 write 시에 동기화 작업이 일어나기 전에 page fault 를 발견하고 해당 페이지를 건드리기 때문입니다.

첫번째 그래프는 테스트 동안에 급격한 저하없이 일관적인 성능을 유지한다는 것을 보여줍니다. Rick의 코드 하나의 데이터베이스에서 쿼리를 했고, 벤치마크는 두번째 변경인 PageFaultException의 향상으로 부터 실제 향상이 일어난 것을 보여줍니다. 대부분 업그레이드를 할 이유가 여기에 있을 것입니다.  해당 버전에서 여러 데이터베이스를 통한 벤치마크에서는 얼마나 성능 향상을 보여줄지 흥미롭습니다.