Hbase 메일링 리스트를 보면 대부분의 User들이 Region Server의 compation과 Hotspotting때문에 고생을 한다. 언젠가 부딪힐 수 있는 부분이라서 정리를 해본다.
Hbase 가이드에 따르면 샤딩해놓은 Region 서버를 미리 만들어 널널하게 데이터들을 분배할 수 있도록 하라고 한다. (pre creation) 마치DB 파티셔닝 정책과 비슷하다.
보통은 Sequential key단위로 row를 Hbase에 저장하면, 하나의 Region Server에 몰릴 수 있다. 따라서 Key를 Sequential하지 않게 만드는 경우도 빈번하다.
이 방법을 해결하기 위해서는 2가지 정도가 쓰였던 것 같다.
첫번째, 000001:key, 0000002:key 와 같이 key를 같이 쓰는 형태로 쓰게 된다. 대신 적절하게 key-value를 분산할 수 있지만 Range Scan시 fully search하게 되니. Hbase에 큰 부하를 주게 한다.
두번째, consistent hashing key를 Hbase의 row로 사용하는 방식인데. 이 방법은 진짜 hashing은 되지만 Range는 도저히 쓸 수 없는 형태가 된다. 그렇지만 Region Hotspotting 을 피할 수 있게 된다.
Range 검색도 쉽게 되게 하고 Hotspotting을 피하는 방법이 있나 궁금했었는데..
sematext.com 라는 빅데이터 분석 및 솔루션 판매 회사에서 기술 블로그에서 간단히 공유된 팁이 있어서 공유하고자 한다.
http://blog.sematext.com/2012/04/09/hbasewd-avoid-regionserver-hotspotting-despite-writing-records-with-sequential-keys/
자세한 내용은 직접 보는 것이 좋을듯 하다.
Sequential Key를 row에 넣으면 특정 Region이 튀는 현상이 발견된다.
아래 식을 이용해서 sequential key를 bucket number, 즉 저장 단위별로 %로 나누어 저장하게 한다.
new_row_key = (++index % BUCKETS_NUMBER) + original_key
이렇게 함으로서, 데이터를 분산하여 cpu 튀는 현상이 없도록 했다.
Scan시 병렬로 읽기 때문에 큰 성능 저하는 없었다고 한다.
이를 바탕으로 hbaseWD (https://github.com/sematext/HBaseWD) 라는 오픈 소스를 공유했다.
예를 들어, 32 buckets으로 나누고. 분산화된 키를 가지고 저장(Put)한다.
byte bucketsCount = (byte) 32; // distributing into 32 buckets
RowKeyDistributor keyDistributor =
new RowKeyDistributorByOneBytePrefix(bucketsCount);
for (int i = 0; i < 100; i++) {
Put put = new Put(keyDistributor.getDistributedKey(originalKey));
... // add values
hTable.put(put);
}
Scan을 진행하는 코드이다.
Scan scan = new Scan(startKey, stopKey);
ResultScanner rs = DistributedScanner.create(hTable, scan, keyDistributor);
for (Result current : rs) {
...
}
Scan한 결과를 가지고 Map-Reduce를 진행할 수 있다.
Configuration conf = HBaseConfiguration.create();
Job job = new Job(conf, "testMapreduceJob");
Scan scan = new Scan(startKey, stopKey);
TableMapReduceUtil.initTableMapperJob("table", scan,
RowCounterMapper.class, ImmutableBytesWritable.class, Result.class, job);
// Substituting standard TableInputFormat which was set in
// TableMapReduceUtil.initTableMapperJob(...)
job.setInputFormatClass(WdTableInputFormat.class);
keyDistributor.addInfo(job.getConfiguration());
HbaseWD의 실제 코드는 그리 많지는 않고.. 현재는 업데이트 되는 것 같지는 않다 ^^;
https://github.com/sematext/HBaseWD/tree/master/src/main/java/com/sematext/hbase/wd
'nosql' 카테고리의 다른 글
[Hbase] 새로 추가된 Zookeeper의 기능 - read/write locks (0) | 2013.04.26 |
---|---|
[Hbase] 버전별 성능 (0) | 2013.04.25 |
[hbase] Hbase 설치하기 (Fully Distributed mode) (1) | 2013.04.23 |
org.apache.hadoop.hbase.MasterNotRunningException 해결하기 (0) | 2013.04.23 |
[hbase] bin/stop-hbase.sh 실행시 종료안되는 현상 (. 만 계속 찍히는 현상) (0) | 2013.04.23 |