2016년 7월 13일 수요일

Flume Hbase Sink 성능 문제의 원인과 해결

Cloudera 플랫폼을 도입하고부터 계속 HBase에 데이터를 넣는 데 성능이 안 좋게 나오고 있었다.
HBase로 데이터를 넣는 건 flume의 hbase sink 기능을 사용하였다.
CDH 버전은 5.7.1 이다.

성능 문제를 해결하기 위해 제일 처음에 Flume 튜닝을 시도하였으나 제대로 되지 않았다.

Cloudera support portal에 case를 open하여 cloudera 엔지니어들의 도움을 지속적으로 받았으나 효과가 없었다.
cloudera 관계자가 region server에 테이블의 영역을 pre-split해보라고 해보았지만 이것도 별 영향이 없었다.

그 이후 HDFS와 HBase의 튜닝을 4일 정도 시도하였다.
HDFS와 HBase에서 write 성능을 향상시키기 위해 여러 설정들을 이리저리 바꾸어 가면서 시도하였지만 역시나 소용이 없었다.
이렇게 해도 저렇게 해도 HBase 쓰기 성능은 달라지지 않았다.
짐작으로 어떤 부분에서 write가 지연되는 현상이 발생할 것이라 생각하였었고 HBase의 설정 상에서 bottleneck이 발생하지는 않나 하면서 또 다시 HBase 설정에 조금씩 변화를 주면서 시도해보았다.
결과는 마찬가지였다.

이렇게 시간을 보내면서 HDFS와  HBase의 설정과는 관계없는 다른 곳에 문제가 있구나 하고 생각이 들었고 다시 flume 쪽에서 문제가 될 부분이 없는지를 확인해보았다.
조금씩 시간을 들여 확인해보니 flume에서 hbase sink를 할 때 사용하던 SimpleAsyncHbaseEventSerializer에 문제가 있었다.

SimpleAsyncHbaseEventSerializer에서 increment column value를 계속 시도하고 있었던 게 지연의 원인이었다.
Increment column value 기능은 RDB의 auto increment 기능과 같이 해당 컬럼의 값을 1씩 증가시켜주는 기능이다.
이 기능의 설정을 하지 않았는데도 계속적으로 이를 시도했던 이유는 flume의 프로퍼티(설정 값) incrementColumn의 값을 디폴트로 'iCol'을 주게 되어 있기 때문이다.
따라서 incrementColumn값이 null이 아니므로 계속적으로 increment column value 시도를 해왔었다.

incrementColumn 값을 설정하지 않으면 null이 되게 코드를 수정하여 적용하고 테이블을 pre-split 하니 한 개의 sink로 max 8만건 처리가 가능하게 되었다.
sink를 4개로 하였을 땐 max 14만건까지 처리하였다.

전반적으로는 꽤나 많은 시간을 이 부분에 할애하였기 때문에 HBase에 대해 여러가지로 공부해보고 생각해볼 수 있었으나 시간 허비가 많이 된 측면이 있다.
Cloudera 엔지니어들이 찾을 수 없는 문제였는지 좀 의문스러우면서 약간의 실망감이 들었다.