2014년 8월 17일 일요일

Couchbase 사용기 - 2

Couchbase 는 기본적으로 key/value 타입의 NoSQL 제품입니다. 다시 말해 Unique 한 Key 을 이용해서 문서(Document)을 빠르게 가져오는 것을 목적으로 한 제품이라는 것이죠. 그렇다면 사용자가 읽어오길 원하는 문서의 Key 을 알고 있다면 언제든지 문서를 가져올 수 있습니다. 실제로 Couchbase SDK 에서는 set() 와 get() 을 통해서 문서를 저장하고 가져올 수 있으며 매우 단순한 형태이기 때문에 초급 개발자도 금새 배울 수 있습니다.
하지만, 현실상 특정 key 의 문서만 가져오는 경우는 매우 드뭅니다. 가까운 예로 게시판의 경우만 해도 특정 조건을 만족하는 데이터(=문서)의 집합을 가져와서 화면에 출력하는 형태가 되죠. Couchbase 는 이러한 것을 map/reduce 기반의 View 을 통해 처리할 수 있도록 하고 있습니다. map/reduce 는 Couchbase 의 독자적인 기술은 아닙니다만, 솔루션마다 처리 방식을 조금씩 다르게 하기 때문에 여기서 Couchbase 의 View 을 통해 Couchbase 만의 특징을 살펴보고자 합니다.

Couchbase 의 웹콘솔에 접속하면 Views 항목을 볼 수 있습니다. 여기서 View 을 생성할 수 있습니다. 이 때 "Design Document Name" 이라는 항목과 "View Name" 을 입력하게 되어 있는데, 쉽게 말해 Design Document Name 은 뷰의 그룹명, View Name 은 View 의 이름입니다. 생성을 하게 되면 "VIEW CODE" 부분에 "Map" 와 "Reduce" 을 입력할 수 있습니다. 모두 Javascript 문법을 이용한 하나의 function 이며, 매개변수는 doc 와 meta 을, View 에서 생성되는 인덱스에 들어가는 정보는 emit() 으로 입력할 수 있습니다.

자세한 사용법을 설명하는 것은 아니므로 구현 부분에 대해서는 다른 기회가 되면 글을 적어보겠습니다. 여기서 설명할 내용은 View 에 대한 특성입니다.

먼저, View 은 처음 생성할 때를 제외하고는 문서를 추가하거나 갱신, 삭제 등의 작업을 할 때 처리된 후 저장됩니다. 처음 생성할 때에는 모든 문서를 읽어서 View 의 인덱스를 구축합니다. 이 구축 작업은 비동기로 이루어지기 때문에 생성 버튼을 눌러도 바로 적용되지 않고 수초~수십초의 시간이 흐른 뒤에야 제대로 View 의 결과가 나타납니다. 그리고 문서가 추가되는 등의 작업이 발생하면 메모리에 저장을 하면서 map/reduce 코드를 통해 인덱스 정보가 생성된 뒤에 2.5.1 까지는 디스크에, 3.0 부터는 메모리에 인덱스 정보가 저장되기 때문에 저장 완료 후 즉시 조회를 하면 바로 적용이 되질 않아서 추가/갱신/삭제된 문서 정보가 제대로 반영이 안되어 있습니다. 2.5.1 이하 버젼에서는 3초 정도 걸리는 경우가 비일비재합니다. 3.0 부터는 메모리에 저장되기 때문에 1초 이하가 될꺼라고 합니다만 완벽히 동기화 된다고 볼 수 없습니다.

그리고 View 는 조건에 대한 처리가 아니라 문서에 대한 처리이기 때문에 사용자가 조회시 보내는 매개변수에 따라 그때그때 조회하는 것이 아니라 인덱스된 문서의 key의 범위 사이의 값을 돌려보내주는 것입니다. 그래서 배열 형태로 2개 이상의 매개변수를 보낼 경우 일반적인 RDBMS 의 검색과는 판이한 검색결과가 나옵니다. 게다가 숫자형의 값일 경우 일반적인 조회에서는 숫자형태로 저장되어 있지만, View 을 생성하면 숫자형이 문자형으로 바뀌기 때문에 인덱스 생성시 1,2,3,...,10,11,12,...,20,21,22,... 와 같은 형태가 아닌 1,10,100,...,11,... 와 같이 정렬이 됩니다. 복합적인 매개변수의 경우도 아래와 같이 됩니다.


  1. [1,"daum","korea"]
  2. [1,"naver","korea"]
  3. [3,"bing","usa"]
  4. [3,"google","usa"]


위와 같이 인덱스가 생성되면(입력 순서에 상관없이 세 값의 순서대로 정렬되어서 인덱스가 생성됩니다) 아래와 같은 형태로 범위검색을 할 수 있습니다.

startKey : [1,"dreamwiz", "korea"]
endKey : [3,"facebook", "usa"]

처음에는 RDBMS 의 or 조건처럼 검색이 되나 싶었습니다만(엔투엠에서도 그런 식으로 이해하시면 될 것 같다고 했습니다만...) 사실 그렇지 않더군요. 어찌보면 더 간단한 것인데요...
추가로 startKey 와 endKey 을 입력한다고 하면 어떤 위치에 값이 들어가게 될까요? 각각 1 번 다음과 3번 다음에 위치하게 될 것입니다. 그러므로 위의 범위 검색 결과는 2 번과 3 번이 되게 됩니다. 이런 식으로 범위 검색을 통해서 이미 입력된 인덱스의 값을 가져오기 때문에 RDBMS 의 like 검색과 같은 것은 이용할 수도 없고, 숫자를 이용한 범위 검색도 불가능합니다. 그래서 항상 View 을 생성하고 난 뒤 원하는 결과가 나오는지 꼼꼼히 확인하는 것이 중요합니다.

좀 더 다양한 검색 결과를 원하신다면 검색엔진과의 연동이 필요합니다. Couchbase 에서는 Elasticsearch 와 연동하는 방법을 제공하고 있습니다. 이 방법을 통해 View 의 map/reduce 방식이 가지는 한계를 어느 정도 극복할 수 있습니다.

또다른 사용기는 다음 글에...

2014년 8월 15일 금요일

Couchbase 사용기 - 1

Couchbase 을 도입해서 Web REST 기반의 서버를 제작했습니다. 실제 서비스를 제공중에 있구요. 동시접속 2만명 테스트도 진행했었는데, Couchbase 는 잘 버틴다는 표현을 쓰기 무색하게...한가로이 데이터를 처리하더라구요. 하나의 요청에 Couchbase 의 문서(Document) 갱신이 최소 2회가 이루어지는데도 말이죠. MariaDB with Galera Cluster 라면 몇 분 마다 한 번씩 SlowQuery 로그가 떨어질 환경이었는데 별 걱정 없이 프로그래밍 할 수 있게 해줘서 다행이다 싶었습니다.

하지만, 게임이 매우 잘되어서 저장공간이 부족해지거나, Log 를 Couchbase 에 담는다거나 해서 용량증설의 시기가 다가오면, 장비의 추가냐 램의 증설이냐를 따져야할 때가 옵니다. 보통은 서버에 램을 추가로 꼽는 것이 훨씬 비용이 저렴하기 때문에 램 증설(Scale-Up)을 고려하게 되지만, 문서의 크기가 점점 불어나서 저장 공간이 부족해질 때에 적합한 것이지 사용자가 늘어나서 증설의 필요성이 생긴 것이라면(다시 말해 문서의 개수가 많아졌을 경우) 장비의 추가(Scale-Out)가 필요하게 되었다고 판단해야 합니다.
이는 Couchbase 가 기본적으로 Sharding 을 지원하기 때문에 장비가 늘어나면 늘어날수록 문서(Document)가 각 서버에 분산 배치되어 처리되기 때문에 서버가 늘어날수록 요청이 서버수만큼 분산되어 전체 처리량을 늘릴 수 있게 되기 때문입니다.

그런데 살짝 딜레마에 빠지게 되는게 두 가지가 있습니다.

먼저, Couchbase 는 가상머신(Cloud Server인 AWS 나 UCloudBiz, 혹은 VMWare, Zen Server 등)보다는 실제머신을 사용할 것을 권합니다. 아무래도 가상머신들은 메모리를 공유하는 형태가 많기 때문에 이 부분에서 속도 문제나 오염 문제가 생길 가능성을 배제할 수 없을 것 같기도 하고, CPU 등의 설정이나 Couchbase 의 네트워크 환경의 문제도 약간 걸림돌이 될 수 있습니다.
특히 가상머신을 이용할 경우 하나의 공인IP 을 여러 가상머신이 공유해서 사용하는 경우가 대부분인데 Couchbase SDK 는 편리한 Connection Pool 을 이용해 접속을 하는 대신, 8091 와 11210 포트를 이용해 Pool 에 등록된 Couchbase Server 에 접속을 하기 때문에 포트 포워딩을 통해 각 서버에 접속할 수 있도록 해줄 수가 없습니다. 좀 더 자세히 설명하자면,


  1. Client 는 Server 의 8091 포트를 통해 접속 시도
  2. Server 는 Client 에게 Clustering 된 Server 접속정보(HOST:PORT 형식) 목록을 제공
  3. Client 는 Connection Pool 에 Server 목록을 저장
  4. 저장된 Server 목록을 이용해 각 Server 에 접속


위와 같은 동작 방식을 취하고, 이는 Couchbase SDK 뿐만 아니라 Couchbase Server 간에도 이와 같은 방식을 취하기 때문에 외부 접속시에만 포트 번호를 임의로 바꿔서 처리하는 포트 포워딩 방식의 처리도 쉽지 않습니다.
그리고, 처음에는 1 대의 머신으로 테스트를 하는 경우가 많아서 간과할 수 있는 부분이 있습니다. Couchbase 는 장비를 기존 Cluster 에 추가할 때에는 IP 혹은 Domain(FQDN)을 이용해서 기존 서버(신규 서버에서 기존 클러스터에 참여하려고 할 때) 혹은 신규 서버(기존 서버에서 신규 서버를 등록하려고 할 때)에 접속해서 연결을 하는데, 위의 2 번에서 돌려주는 Server 접속정보가 이 때 등록한 IP 혹은 Domain 이 됩니다. 그래서 가상머신에서 가상IP 을 이용해서 등록을 하게 될 경우 외부에서 Couchbase SDK 을 이용한 Client 연결이 불가능해질 수 있습니다.
이에 대한 해결 방법을 고민한 결과, 저는 hosts 파일을 모든 Client/Server 에 등록해서 연결하는 방식을 취하고 있습니다. IP 나 제대로된 DNS 을 이용할 경우 가상머신을 이용할 때에 꼬이게 되는 부분이 있어서 이렇게 처리했습니다. 혹시 더 좋은 방법이 있으신 분은 조언 부탁드립니다(zepinos@gmail.com).

또 다른 하나는, 실제 머신을 이용할 때입니다. 기업에서, 특히 저와 같이 게임 업계 쪽에서 Cloud 서비스을 이용하는 것은 바로 확장성입니다. Scale-Out 와 Scale-In(장비 줄이기) 가 매우 쉽기 때문입니다. 일반적으로 실제 머신을 이용하게 될 경우 IP 는 공인IP 을 직접 부여하는 경우가 많기 때문에 먼저와 같은 문제는 크게 고민거리가 안될 수 있습니다. 하지만, 실제 장비는 장비 추가가 급하게 이루어져야 할 때 크게 문제가 발생합니다. 장비의 도입까지는 서버 업체 및 사양 결정, 견적 요청, 납품 등의 프로세서를 거치는데 이 기간이 보통 수 주가 소비되는 경우가 많습니다. 서비스가 크게 흥행하게 될지 아닐지 모르는 상황에서 무턱대고 장비를 여러개 도입하기도 힘들고, 그렇다고 사양이 높다고 해서 성능이 올라가는 형태의 솔루션이 아니기 때문에 요청 숫자에 따른 장비 확보는 쉽지 않은 문제가 있습니다.
또한, Sharding 이 기본적으로 지원되어서 처리량을 늘려나갈 수 있는 장점이 존재하는 대신에 장비를 추가하거나 제거할 때에는 반드시 Rebalance 작업을 진행해야 합니다. 한 대의 장비에는 전체 문서(Document)의 1/N 만큼의 문서를 가지고 있고 해당 문서를 전담해서 처리한다고 생각하면 편한데, 서버를 제거할 경우에는 문서를 다시 1/(N-1) 만큼 나눠서 각 서버에게 재배치해야 하는 일이 발생한다는 것이죠. 그 작업을 Rebalance 라고 합니다. 아무리 메모리와 빠른 내부 네트워크를 이용해서 일을 처리한다고 해도 문서양이 많을 경우 수십분 이상 소요될 수 있는 작업이 됩니다. 물론 이러한 Rebalance 작업은 Live 환경에서 적용이 가능하기 때문에 작업 공지를 걸고 전체 서비스를 차단한 뒤 진행할 필요가 없어서 매우 좋긴 하지만 문제가 발생할 수 있다는 걱정 때문에 쉽사리 하지 못한다는 문제가 있습니다. 그리고, 각 서버는 Replica 라고 하는 백업 정보를 가지고 있는데 보통은 서버 대수보다 한 개 적게(N-1) 가지고 있습니다. 즉 1~3 번 서버가 존재한다면 Replica 는 2 개를 설정하는게 좋은데(Bucket 생성 시 선택할 수 있고, 언제든지 바꿀 수 있습니다) 1번 서버의 경우 메모리에는 자신에게 할당된 문서들을, Replica 에는 2 개의 백업(2, 3 번 서버에 할당된 문서)을 저장하게 되는 것입니다. 그래서 서버가 Rebalancing 없이 갑작스럽게 중지가 되어도 Replica 을 이용해서 문서 내용을 복구할 수 있습니다. 그리고 중지된 서버의 요청도 활성화된 서버가 Replica 의 내용을 메모리로 올려서 대신 제공해줍니다. 하지만, 실제 서버를 이용하게 될 경우 이런 불안한 상태를 장비 추가가 이루어질 때까지 불안하게 쳐다보고 있어야 한다는 단점이 있습니다. 게다가 Rebalance 에 대한 이해 없이 그냥 강제로 서버를 빼고 그냥 추가만 해버리면 데이터가 유실되는 끔찍한 사태를 겪을 수 있습니다.

그러므로 많은 노하우가 축적된 RDBMS 보다는 좀 더 신중하게 접근할 필요가 있으며 단순히 인터넷의 문서(Couchbase 공식 홈페이지에는 자세한 영문 문서가 제공됩니다)만 보고 작업했다가 실제 서비스 도중 재앙을 맞딱드릴 수 있으니 정식 지원 서비스에 가입을 하거나 정식 지원 서비스를 받은 적이 있는 엔지니어를 고용해서 서비스 하는 것을 권하고 싶습니다.



또다른 사용기는 다음 글에...