본문 바로가기

IT for developer/Hadoop+Nosql

Performance Tuning Hbase


HBase: The Definitive Guide 책에서 발번역 -early edition 번역

1. 가비지 컬렉션
region server인 경우 가비지 컬렉션 파라미터를 조정할 필요가 있다.
마스터인 경우 많은 로드가 발생하지 않으므로 다음의 셋팅들은 region server들에게만 필요하다.

HBase를 효과적으로 수행하는데 왜 가비지 컬렉션을 할까?
이 문제는 JRE가 프로그램이 무엇을 하는지, 어떻게 객체를 생성하는지 등에 관한 추정에 관여하는 것으로 부터 발생된다. 이 가정들은 대부분의 경우 잘 동작한다. 그리고 JRE는 프로세스가 동작하고 이을 때 이런 추정들을 조정하는 휴리스틱 알고리즘을 가지고 있다. 

그러나 region 서버와 같은 경우 잘 다루지 못한다. 이는 작업량, 특히 JRE 추정만으로 안전하게 의존할수 없는 수준의  과도한 쓰기와 메모리 할당 때문이다.

과도한 쓰기의 경우  memstores는 빈번하게, 다양한 사이즈의 객체들을 생성하고 폐기한다. 이 데이터가 메모리 버퍼안에 모여져 설정된 최소 플러쉬 사이즈를 넘어설 때까지 남아있을 필요가 있다. (hbase.hregion.memstore.flush.size 또는 테이블 레벨에서 지정)

일단 데이터가 해당 사이즈를 넘어서면 디스크에 플러쉬되고 새로운 파일을 생성한다. 디스크에 쓰여진 데이터는 자바 힙에서 다양한 곳에 남겨져 있기 때문에 (다른 시간 때에 클라이언트에 의해 쓰여졌다고 추정) 힙에 구멍으로 남겨진다.

얼마나 오래 데이터가 메모리에 있었냐에 따라, 자바 힙의 세대 구조(generational architecture)에서 다양한 위치에 남겨진다.

빨리 삽입되고 빠르게 플러쉬되는 데이터는 young 세대이라 불리우는데 있다. 이 공간은 빨리 취소될수 있고 아무로 해도 없다.

반면에, 메모리에 오래 머물러 있는 데이터인 경우, (예를 들어 덜 빠르게 삽입되는 컬럼 패밀리)  old 세대에 놓여진다. young과 old의 차이점은 주로 사이즈에 있다. young 세대는 128 MB에서 512MB 사이에 있는 반면에 old 세대는 남아있는 사용가능한 힙을 가지고 있다.- 수 기가 바이트

가비지 컬렉션 옵션은 hbase-env.sh 파일에 HBASE_OPTIONS 또는 HBASE_REGIONSERVER_OPTS에 추가해주면 된다. (HBASE_REGIONSERVER_OPTS 추천. -> 마스터는 적용되지 않으므로)



young 세대 사이즈를 지정하는 방법은 두가지가 있다.


-XX:MaxNewSiz=128 -XX:NewSize-128m


or

-Xmn128m




128MB 사용하는 것은  JVM 매트릭을 관찰하기 위한 좋은 시작점이다. new 세대를 만족스럽게 사용하는지 확인할 필요가 있다. regsion 서버들의 심하게 느리다면 값을 증가시켜야만 한다. 그렇게 하지 않으면 new  세대 공간으로 부터 객체들을 컬렉팅하는데 대부분의 시간을 소비하기 때문에 CPU 로드가 급격히 증가되는것을 볼 수 있을 것이다.



두 세대 모두 디스크에 쓰여진 데이터(and 생성되고 폐기된 다른 객체들)에 의해 발생된 구멍들을 재사용하기 위하여 JRE에 의해 관리될 필요가 있다. 만약에 애플리케이션이 그러한 구멍에 적합하지 않은 힙의 양을 요청한다면 JRE는 조각난 힙을 꽉 채울필요가 있다. 이는 young 부터 old 세대까지 오래 살아있는 개체들의 promotion처럼 내포된 요청들을 포함한다. 만약에 이게 실패하면 가비지 컬렉션 로그에서 promotion failure를 볼것이다.


JRE에 가비지 컬렉션 로그를 자세히 볼수 있도록 설정하려면 다음과 같이 하면 된다.

0verbos:gc -XX:+PringGCDetails -XX:+PrintGCTimeStamps \ -Xloggc:$HBASE_HOME/logs/gc-$(hostname)-hbase.log"    


 오랫동안 멈춰있는 경우 "concurrent mode failure" or "promotion failed" 메세지를 볼 수 있을 것이다.



힙 세대를 다시 쓰는 과정을 가비지 컬렉션이라고 부르고, 다양한 가비지 컬렉션 구현들을 지정하기 위해 사용될수 있는 JRE 파라미터들이 있다. 추천하는 값들은

 

-XX:+UseParNewGC and -XX:+UseConcMarkSweepGC



첫 번째 옵션은 young 세대를 위해 Parallel New Collector를 사용한다는 설정이다.
young 세대 힙을 치우기 위해서 자바 프로세스가 완전히 멈춘다.  작은 사이즈이기 때문에 프로세스는 오래걸리 않는다. 일반적으로 수백밀리 초 이하이다.

이는 더 작은 young 세대는 받아들여 질 수 있지만 old 세대는 그렇지 않다. 최악의 경우 수초가 멈춰있는 결과를 초래할 수도 있다. 일단 설정된 Zookeeper 세션 타임아웃에 도달하면 이 서버는 마스터에 의해 포기 되어진다. 멈춤을 유발한 가비지 컬렉션으로부터 되돌아가면 자신이 포기되고 셧다운되어 있다는것을 알 수 있다.

이것은 Concurrent Mark-Sweep Collect (CMS)사용으로 완화할 수 있다. (두 번째 옵션). 자바프로세스를 멈추는 것 없이 동시에 수행하도록 시도한다. (Full Gc를 수행할때 애플리케이션을 멈추고 진행하는 것이 아니라, 일부는 애플리케이션이 돌아가면서 수행하고, 나머지 최소의 작업만 애플리케이션이 멈췄을 때 수행하도록 한다.) 이는 부가적인 작업이고 CPU 로드를 증가시킨다. 그러나 조각난 old 세대 힙을 다시 쓰기위해 멈춰지는 것(가비지 컬렉터에게 모든것을 멈추게하고 쓰레기들을 치우도록하는 promotion error를 만날 때 까지)을 피할 수 있다.


그밖의 옵션 (http://wiki.ex-em.com/index.php/JVM_Options 참조 - 발췌)

CMSIncrementalMode
- Full GC 작업을 점진적으로 진행한다. 일반적으로 CMS 컬렉터는 old 세데가 어느 정도 이상 점유하게 되면 Concurrent Full Gc 작업을 시작한다. 반면 이 옵션이 활성화되면 old 세대의 사용률과 무관하게 백그라운드에서 점진적으로 old 세대에 대한 GC 작업을 수행한다.

CMSInitiatingOccupanyFraction
- CML Collecton이 시작되는 임계값을 결정한다. 만일 이 값이 50이면 old 세대가 50%이상 사용되면 Concurrent Full GC가 시작된다. 이 값의 기본값은 "-1"이다. 옵션이 지정되지 않으면 old 세대가 92%정도 사용될 때 Concurrent Full GC가 시작된다. 이 옵션의 값이 작으면 CMS Collection이 그만큼 빨리 동작하기 때문에 Promotion failure 에 의한 Stop The World GC(애플리케이션이 멈추는것) 작업이 발생할 확률이 그만큼 줄어든다.
 

추천 초기 셋팅

export HBASE_REGIONSERVER_OPTS="-Xmx8g -Xms8g -Xmn128m -XX:+UseParNewGC \

  -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc \

  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps \

  -Xloggc:$HBASE_HOME/logs/gc-$(hostname)-hbase.log"

 
0.90 버전에서는 힙 조각 이슈를 완화하는 개선된 매커니즘을 소개하고 있다. 

KeyValue 인스턴스들이 디스크에 플러쉬되면 old세대 힙에 구멍이 생기게 된다. 더이상 새로운 할당을 할만한 충분한 공간을 가지고 있지 않으면 JRE는 애플리케이션을 멈춰버리고 GC를 수행한다. (남아있는 액티브 객체들을 컴팩팅하여 전체 힙 공간을 다시 쓴다.

MSLAB(Memstore-Local Allocation Buffer) 은 KeyValue 인스턴스를 포함하고있는 고정된 사이즈의 버퍼이다. 버퍼는 새롭게 추가된 KeyValue에 딱 맞지 않을때 마다 새로운 버퍼를 생성한다.

이것은 0.92버전부터 디폴트로 활성화되어 있고 0.90버전에서는 비활성화되어 있다.

hbase.hregion.memstore.mslab.enabed 설정 속성을 사용할 수 있다.

고정된 사이즈의 버퍼는 hbase.hregion.memstore.mslab.chunksize 속성에 의해 제어된다. 디폴트는 2MB이다.
KeyValue 인스턴스들을 기반으로하여 이 값을 조정해야만 한다. 만약 더 큰 셀들이 저장된다면 더 큰 셀을 저장한다면(예. 100킬로 바이트), 몇몇 쉘보다 좀 더 적절케하기위하여 MSLAB 사이즈를 증가해야만 한다.
 

Compression

HBase는 컬럼  패킬리 레벨에서 활성화될 수 있는 압축 알고리즘들을 제공한다.
 
./bin/hbase org.apache.hadoop.hbase.util.CompressionTest