[발 번역] HBase Replication Overview

해당 블로그는 KT UCloud 의 지원을 받고 있습니다.

해당 글은 http://www.cloudera.com/blog/2012/07/hbase-replication-overview-2/ 라는 글을 발 번역한 것입니다. cloudera의 경우 하둡 에코시스템을 이끌고 있는 메인 기업중에 하나인데, 관련 구조에 대해서도 좋은 글이 자주 올라오는 사이트이니, 관심이 있으시면 유심히 살펴보시면 좋은 자료가 많을듯 합니다.

HBase Replication Overview

HBase의 리플리케이션은 하나의 HBase 클러스터로 부터 분리된 다른 HBase 클러스터로 데이터를 복사하는 방법입니다. 원본 클러스터에서 다른 클러스터로 데이터를 집어넣는 트랜잭션을 기초해서 동작합니다. HBase Jargon에서는 푸쉬를 하는 클러스터는 마스터, 트랜잭션을 받는 쪽은 슬레이브라고 합니다. 해당 푸쉬 트랜잭션은 비동기적으로 동작합니다. 그리고 해당 트랜잭션은 설정된 크기(기본적으로 64MB) 에 따라서 배치작업으로 일어납니다. 비동기 모드는 마스터에는 최소한의 오버헤드만 초래하고, 배치 작업에서 변경 사항을 보내는 것은 총 전송량은 증가시킵니다.

해당 글에서는 가능한 유즈케이스에 대해서 논의합니다. 아키텍처와 HBase 리플리케이션 모드는 CDH4(0.92버전을 기반으로 한) 에서 지원되고 있습니다. 리플리케이션 설정과 부트스트래핑, 장애 안정성에 대해서는 다음 번 블로그 글에서 얘기하도록 하겠습니다.

Use cases

HBase 리플리케이션은 데이터 센터간 리플리케이션을 지원합니다. 이것은 마스터 사이트가 장애시에도, 슬레이브 서버가 실시간 트래픽을 처리할 수 있어서. 장애 복구 시나리오에도 이용될 수 있습니다. HBase 리플리케이션이 명시적으로 자동 장애복구를 의미하지는 않기 때문에, 슬레이브 클러스터에서 마스터로 스위칭 하는 작업은 유저가 직접 해야 합니다. 그 뒤에, 마스터 클러스터가 정상으로 회복되면, CopyTable blogpost 에서 설명한거 처럼 마스터 클러스터에(시작/정지 타임스탬프를 제공함으로써) 차이가 나는 부분을 복사해 주기 위해서 CopyTable Job을 수행할 수 있습니다.

리플리케이션의 다른 유즈 케이스는 유저가 HBase 클러스터에 MapReduce 작업을 해서 부하가 올라갈 경우에 유용합니다. 마스터 노드의 성능에 아주 조금 영향을 주긴 하지만, 슬레이브 클러스터에서 해당 MapReduce 작업을 할 수 있습니다.

Architecture

HBase 리플리케이션의 기본 원칙은 마스터에서 발생했던 모든 트랜잭션을 슬레이브에서 재현하는 것입니다. 이것은 다음 섹션에서 설명하는 것처럼, 마스터 클러스터에 있는 WAL 파일안의 WALEdits(WAL에 쓰여져 있는 변경 기록들) 을 재현함으로써 수행됩니다. 이 WALEdits들은 슬레이브 클러스터의 Region 서버들로 전송되고, 필터링 후에( 어떤 변경 기록들은 리플리케이션이 되지 않는 범위일 수 있습니다.), 지정된 사이즈로 저장됩니다.(기본 64MB)  WAL 리더가 현재 WAL 파일의 끝에 다다르면, 그 때 까지 읽은 WALEdits를 전송하려고 준비할 것입니다. 리플리케이션이 비동기 모드를 이용하므로,  수 분을 소모하는 무거운 헤비 어플리케이션에서는 마스터에 비해서 복제가 느릴 수 있습니다.

WAL/WALEdits/Memstore

HBase 에서 모든 변경 작업(Puts/Deletes) 는 특정 Region 서버의 memstore에 저장되고 동시에 WAL 파일안에 WALEdit 형태로 저장됩니다. WALEdit는 하나의 트랜잭션을 나타내는 오브젝트이고, 하나 이상의 변경 작업을 가지고 있습니다. HBase가 Single-Row 레벨의 트랜잭션을 지원하기 때문에, WALEdit 는 오직 하나의 로우에 대한 정보만 가지고 있습니다. WAL 파일들은 설정된 시간(기본적으로 60분 마다) 이후에 지속적으로 계속 변경되므로, 특정 시간에 하나의 Region 서버에는 오직 하나의 WAL 파일만 존재합니다.

IncrementColumn 값의 경우는 CAS(check and substitute) 동작으로써, WAL에 쓰여질 때 Put으로 변경되어집니다.( 역자 주: CAS 연산은 하나의 오퍼레이션이 Atomic 한 것을 보장하기 위한 연산입니다. LockFree 쪽을 살펴보게 되면 핵심적으로 사용되는것이 CAS 연산이고, CPU Operation 적으로 Atomic이 보장되는 명령을 사용합니다. )

memstore 는 메모리에 있고,  sorted map 에 Region에 저장되는 key/value 이 저장되더 있습니다. region 의 하나의 컬럼 패밀리 마다 하나의 memstore가 있습니다. memstore는 설정된 크기에 도달할때 마다(기본적으로 64MB) HFile 형태로 디스크로 저장됩니다.

WAL에 저장하는 것은 설정가능하지만, region 서버 장애시 데이터 유실을 피하기 위해서 필요합니다.  Region 서버 장애시에, 가지고 있는 모든 memstore 를 읽어버리게 될 것입니다. Region 서버가 장애가 나면, WAL에 있는 데이터들을 복구하기 위해서 Log splitting process에 의해서 모든 WAL 내용이 재현되게 됩니다.

또, 리플리케이션이 동작하기 위해서는 WAL이 무조건 동작해야 합니다.

ClusterId

모든 HBase 클러스터는 UUID 형태로 HBase 에 의해서 자동으로 생성되는 ClusterId를 가지고 있습니다. ClusterId는 리스타트시에 바뀌지 않기 의해서 파일시스템에 저장됩니다.(항상 HDFS) 그리고 zookeeper의 /hbase/bhaseid znode 에 저장됩니다. 그리고 마스터/마스터 acyclic 리플리케이션에 이용됩니다. WAL은 Region 서버안에 저장된 Region 들의 변경정보를 가지고 있습니다. 리플리케이션 코드는 리플리케이션 범위안에 있는 모든 key/value 에 대해서 읽어들이고 필터링합니다. key/value 에 있는 컬럼 패밀리 속성 값을 읽고, 이것을 WALEdit 의 컬럼 패밀리 맵 데이터 구조체와 비교하므로써 해당 작업을 수행합니다. 리플리케이션해야 하는 범위에 포함된 key/value의 경우에는, key/value의 clusterId 값을 해당 HBase ClusterId 값으로 수정합니다.

ReplicationSource

ReplicationSource는 Region 서버 프로세스 안에 있는 자바 스레드 객체로써, WAL 정보를 지정된 슬레이브 클러스터로 복제하는 작업을 하게 됩니다. 이것은 리플리케이션되어야 하는 로그 파일을 담고 있는 우선 순위 큐를 가지고 있습니다. 로그가 처리되는 만큼, 큐에서는 제거됩니다. 우선 순위 큐는 로그 파일이 생성된 시간(로그 파일에 추가된 시간)을 기준으로 비교합니다. 그래서 생성된 시간의 순서와 같은 순서로 처리되게 됩니다.( 오래된 로그가 먼저 처리됩니다. ) 우선 순위 큐에 오직 하나의 로그 파일만 있다면,  그것은 현재 WAL을 의미하므로, 지워지지 않을 것입니다.

Role of Zookeeper

Zookeeper 는 HBase 리플리케이션에서  중요한 역할을 합니다. Zookeeper는 슬레이브 클러스터를 등록하거나, 리플리케이션을 시작/중지 하거나, 새로운 WAL을 큐에 넣거나, Region 서버의 장애를 핸들링 하거나 등의 대배분의 중요한 리플리케이션 관련 작업들을 관리합니다. 항상 동작하기 위해서, 안정적인 Zookeeper Quorum(최소 3대 이상의) 을 사용하는 것이 권장됩니다.  Zookeeper 개별적으로 동작해야 합니다.(HBase 에 의해서가 아니라, 역자 주: HBase 옵션 중에 Zookeeper를 자체적으로 띄우는 설정이 있는데, 이것을 의미하는 듯 합니다.) 아래의 내용들은 마스터 클러스터에서 사용중인 리플리케이션 관련된 znode 들의 구조에 대한 예입니다.( ‘:’ 뒤에 내용이 znode의 데이터입니다. )

<div>
<pre>/hbase/hbaseid: b53f7ec6-ed8a-4227-b088-fd6552bd6a68
….
/hbase/rs/foo1.bar.com,40020,1339435481742:
/hbase/rs/foo2.bar.com,40020,1339435481973:
/hbase/rs/foo3.bar.com,40020,1339435486713:
/hbase/replication:
/hbase/replication/state: true
/hbase/replication/peers:
/hbase/replication/peers/1: zk.quorum.slave:281:/hbase
/hbase/replication/rs:
/hbase/replication/rs/foo1.bar.com.com,40020,1339435084846:
/hbase/replication/rs/foo1.bar.com,40020,1339435481973/1:
/hbase/replication/rs/foo1.bar.com,40020,1339435481973/1/foo1.bar.com.1339435485769: 1243232
/hbase/replication/rs/foo3.bar.com,40020,1339435481742:
/hbase/replication/rs/foo3.bar.com,40020,1339435481742/1:
/hbase/replication/rs/foo3.bar.com,40020,1339435481742/1/foo3.bar..com.1339435485769: 1243232
/hbase/replication/rs/foo2.bar.com,40020,1339435089550:
/hbase/replication/rs/foo2.bar.com,40020,1339435481742/1:
/hbase/replication/rs/foo2.bar.com,40020,1339435481742/1/foo2.bar..com.13394354343443: 1909033

Figure 1. Replication znodes hierarchy

Figure 1 에서 보여주듯이, 마스터 클러스터에는 3대의 Region 서버가 있고, 이름은 foo[1-3].bar.com 입니다. 다음 3개의 znode 들이 리플리케이션과 연관이 있습니다.

  1. state: 해당 znode는 리플리케이션이 켜져있는지 아닌지에 대한 정보를 알려줍니다. 모든 기본 단계에서 실제 동작 전에 해당 값을 체크하게 됩니다.( 리플리케이션 큐에 새로운 WAL 파일을 집어넣는다든지, 로그 파일을 읽어서 WALEdit들 만든다든지 등의 ) 이것은 hbase-conf.xml 에 있는 “hbase.replication” 값이 true 일 때, 설정되게 됩니다. 해당 값은 hbase shell 에서 “start/stop replication” 명령을 사용할 때도 설정되게 됩니다. 다음번 블로그 포스트에서 해당 내용을 얘기하도록 하겠습니다.
  2. peers: 해당 znode는 자식노드로 연결된 peers 와 slaves 들에 대한 정보를 가지고 있습니다. 해당 Figure 1에서 peerId 가 1인 하나의 슬레이브만 존재합니다. 그리고 해당 값은  다음 형태의 연결 정보입니다. (Zookeeper_quorum_of_slave:Zookeeper_client_port:root_hbase_znode), Zookeeper_quorum_of_slave는 ‘,’ 로 구분되는 zookeeper 서버 목록입니다. peerId znode의 이름은 피어를 추가하는 동안 주어진 이름과 동일합니다.
  3. rs: 해당 znode는 마스터 클러스터 내의 Active Region 서버의 목록을 저장하고 있습니다. 각 Region서버 znode 들은 복제되어야 하는 WAL들의 목록을 가지고 있고, 해당 log znode 들의 값은 null (아직 리플리케이션을 위한 로그가 열리지 않았을 경우 )이거나, 해당 log 파일에서 현재 읽은 위치 정보 입니다. WAL znode 의 byte offset 값은 WAL 파일에서 현재 읽고, 리플리케이션 되어서 응답 받은 로그 파일의 위치를 가리킵니다. 슬레이브 클러스터가 하나 이상이라면, 리플리케이션 지행 사항은 각각 많이 다를 수 있습니다.( 예를 들어, 하나가 다운되었다고 가정하면 ) 모든 WAL 은 rs 아래 peerId를 자체적으로 가지고 있습니다. 그리고, 위의 figure 1에서, WAL znode 들은 /rs//1 아래에 있고 “1”은 peerId 입니다.

Replication Modes

HBase 리플리케이션은 3가지 모드로 셋팅 가능합니다.

  1. Master-Slave: 해당 모드에서는, 리플리케이션은 한 방향으로만 진행됩니다. 예를 들어, 하나의 클러스터로 부터 트랜잭션이 다른 클러스터로 들어갑니다. 슬레이브 클러스터는 다른 클러스터과 비슷하고, 자기 소유의 테이블이나 트래픽 등을 가지고 있습니다
  2. Master-Master: 해당 모드에서는, 리플리케이션은 같거나 다른 테이블을 위해 양방향으로 이루어집니다. 예를 들어, 모든 클러스터는 마스터이자, 슬레이브로써 동작하게 됩니다. 같은 테이블을 리플리케이션 하는 경우에, 혹시 끝나지 않는 루프가 발생할지도 모른다고 생각할 수 있지만, 원본 클러스터에서 변경 작업(Put/Delete) 에 ClusterId를 지정함으로써 이런 상황을 피하게 됩니다. Figure 2는 태양과 지구라고 명명된 두대의 클러스터를 이용해서 이것을 설명합니다. Figure 2에는 두 HBase 클러스터를 나타내는 두 개의 블럭이 있습니다. 각각 ClusterId 100 과 200을 가지고 있고, 각 클러스터는 ReplicationSource 를 가지고 있고, 각각, 자신의 ClusterId 와 리플리케이션을 해야하는 슬레이브 클러스터의 ClusterId 를 가지고 있습니다.
    Figure 2. Sun and Earth, two HBase clusters
    클러스터 “태양”이 두 클러스터 간에서 리플리케이션되어야 할 범위에 있는 새로 발생한 변경작업 M이 발생했다면, 그것은 기본으로 설정된 ClusterId(OL)를 가지게 될 것입니다. Replication Source 인스턴스인 ReplicationSrc-E는 해당 변경 작업의 ClusterID를 자신의 ClusterId(100) 와 동일하게 설정할 것입니다. 그리고 클러스터”지구”로 보낼것입니다.  그리고 Cluster “지구” 가 해당 변경사항을 받았을 때, 정상적인 경우에, 그것을 수행하고 WAL에 변경 사항을 저장할 것입니다.  변경 사항의 CluseterId는 클러스터”지구” 의 로그 파일안에 남겨져 있을 것입니다. 클러스터”지구”의 ReplicationSource 인스턴스 ReplicationSrc-S가 해당 변경 작업을 읽고, 변경 사항의 ClusterId를 체크해서 그것이 자신의 슬레이브 클러스터의 ClusterId 와 같은 지를 비교한 다음 해당 값이 동일하면 해당 변경 작업에 대한 WALEdit 를 만드는 것을 하지않고 넘어가게 됩니다.
  3. Cyclic: 해당 모드에서, 두개의 HBase 클러스터 이상이 리플리케이션 셋팅에 참여하게 됩니다. 그리고 다양한 마스터-슬레이브, 마스터-마스터 리플리케이션의 조합이 두 개 이상의 클러스터 간에 설정될 수 있습니다. 위의 두 클러스터가 해당 케이스를 잘 다루고 있고, 사이클을 가지는 새로운 상황이 있습니다.  Figure 3. A circular replication set up

Figure-3 는 원형 리플리케이션 설정을 보여줍니다. 클러스터”태양” 은 클러스터 “지구”로 리플리케이션을 하는 중이고, 클러스터”지구”는 클러스터”금성”으로, 클러스터 “금성”은 클러스터 “태양”으로 리플리케이션 중이니다.
클러스터”태양”이 다른 클러스터로 리플리케이션 해야 하는 변경 사항이 발생했을 때, 위의마스터/마스터  리플리케이션에서 설명한 대로 클러스터 “지구”로 리플리케이션이 될 것입니다. 클러스터”지구”의 ReplicationSource 인스턴스 ReplicationSrc-V 는 WAL 파일을 읽고, 변경 사항을 본 다음 클러스터 “금성”으로 리플리케이션 합니다. 변경 사항의 ClusterId는 클러스터”태양”의 것으로 클러스터”금성”에서도 계속 유지됩니다. 그리고 해당 클러스터에서는 클러스터”태양”을 위한 Replication Source 인스턴스인 ReplicationSrc-S 는 해당 변경 작업의 ClusterId가 자신의 슬레이브 클러스터의 ClusterId 동일 한 것을 체크해서 해당 리플리케이션을 건너뛰게 됩니다.(역자 주: Figure 3의 그림이 조금 잘못되어 있어서 추가 정보를 넣습니다.  그리고 간단하게 해당 내용을 요약하면 최초에 리플리케이션을 발생시킨 클러스터 Id가 리플리케이션 시에 계속 전달되고 슬레이브 클러스터 정보와 비교해서 동일하면 건너뛴다가 핵심입니다. 너무 어렵게 설명되어 있어서 쿨럭…

#Cluster”태양” : 지구로 리플리케이션 하기 위한 ReplicationSrc-E 를 가지고 있습니다.

#Cluster”지구” : 금성으로 리플리케이션 하기 위한 RepliationSrc-V를 가지고 있습니다.( 계속 ReplicationSrc-S를 가진 것으로 나오는데 이전 그림을 재 활용해서 생긴 오류인거 같습니다. )

#Cluster”금성” : 태양으로 리플리케이션 하기 위한 ReplicationSrc-S를 가지고 있습니다.

Conclusion

HBase 리플리케이션은 재해 복구 시스템에서도 사용할 수 있는 매우 강력한 기능입니다. 0.90 버전에서는 맛보기 기능 정도로 추가 되고, HBase와 함께 발전되고 있습니다. 마스터/마스터 리플리케이션 이라든지 acyclic 리플리케이션(0.92에서 둘 다 추가되었습니다.), 피어 레벨 리플리케이션 설정/비설정 기능등이 있습니다.( 0.94에서 추가되었습니다. )

다음 블로그 포스트에서는 HBase 리플리케이션의 설정등의 다양한 동작 기능들에 대해서 얘기해보도록 하겠습니다.