Apache HBase 케이스 스터디
Apache HBase 케이스 스터디 (Case Studies)
실제 운영 환경에서 마주친 HBase 성능·장애 진단 사례들을 모아 둔 페이지예요. 클러스터 문제를 진단하는 유용한 지침서가 되어 줍니다.
출처: 문서
본문
개요 (Overview)
이 챕터는 Apache HBase 클러스터 문제를 진단하는 데 유용한 청사진이 될 다양한 성능 및 트러블슈팅 케이스 스터디를 설명해요. 성능과 트러블슈팅에 대한 자세한 내용은 Apache HBase Performance Tuning과 Troubleshooting and Debugging Apache HBase를 참고하세요.
스키마 설계 (Schema Design)
스키마 설계 케이스 스터디는 여기서 확인하세요: Schema Design Case Studies
성능/트러블슈팅 (Performance/Troubleshooting)
케이스 스터디 #1 (단일 노드의 성능 문제) (Case Study #1 (Performance Issue On A Single Node))
시나리오 (Scenario)
예정된 재부팅 이후 한 데이터 노드가 비정상적인 동작을 보이기 시작했어요. HBase 테이블에 대해 정기적으로 실행되며 보통 56분에 끝나던 MapReduce 작업이 3040분이 걸리기 시작했어요. 이 작업들은 일관되게 문제가 있는 데이터 노드에 할당된 map·reduce 태스크를 기다리는 것으로 확인됐어요(예: 느린 map 태스크들은 모두 같은 Input Split을 가졌어요). 상황은 분산 복사 중에 절정에 달했는데, 뒤처진 노드 때문에 복사가 심각하게 지연됐어요.
하드웨어 (Hardware)
Datanode:
- 12코어 프로세서 2개
- Enterprise SATA 디스크 6개
- 24GB RAM
- 본딩(bonded) 기가비트 NIC 2개
네트워크:
- 10 Gigabit top-of-rack 스위치
- 랙 사이 20 Gigabit 본딩 인터커넥트.
가설 (Hypotheses)
HBase "핫 스팟" Region
우리는 익숙한 고통의 지점을 겪고 있다고 가설을 세웠어요: HBase 테이블의 "핫 스팟" region이죠. 키 공간 분포가 고르지 않으면 엄청난 수의 요청이 단일 HBase region으로 몰려 RegionServer 프로세스를 압도하고 응답 시간이 느려질 수 있어요. HBase Master 상태 페이지를 조사해 보니 문제의 노드에 대한 HBase 요청 수가 거의 0이었어요. 또한 HBase 로그를 조사한 결과 진행 중인 region split, 컴팩션, 기타 region 전환이 없었어요. 이는 "핫 스팟"이 관찰된 느림의 근본 원인이 아니라는 것을 사실상 배제했어요.
비로컬(non-local) 데이터를 가진 HBase Region
다음 가설은 MapReduce 태스크 중 하나가 DataNode에 로컬이 아닌 데이터를 HBase에서 요청해서, HDFS가 네트워크를 통해 다른 서버에서 데이터 블록을 요청하게 만든다는 것이었어요. DataNode 로그를 조사해 보니 네트워크를 통해 요청되는 블록이 거의 없었어요. 이는 HBase region이 올바르게 할당됐고 필요한 데이터 대부분이 노드에 있었음을 나타내요. 이는 비로컬 데이터가 느림을 유발할 가능성을 배제했어요.
스와핑이나 과부하·고장난 하드 디스크로 인한 과도한 I/O Wait
Hadoop과 HBase가 원인이 아닐 것이라 결론을 내린 뒤 DataNode 하드웨어 트러블슈팅으로 넘어갔어요. Java는 설계상 주기적으로 전체 메모리 공간을 스캔해 가비지 컬렉션을 수행해요. 시스템 메모리가 심하게 과다 약정(overcommitted)되면 Linux 커널은 악순환에 빠질 수 있는데, Java가 가비지 컬렉션을 실행하려 할 때 Java 힙을 디스크와 RAM 사이에서 앞뒤로 스와핑하는 데 모든 자원을 소모하게 돼요. 또한 고장난 하드 디스크는 오류를 반환하며 포기하기 전에 읽기·쓰기를 여러 번 재시도하는 경우가 많아요. 실행 중인 프로세스가 읽기·쓰기 완료를 기다리므로 높은 iowait로 나타날 수 있어요. 마지막으로 성능 한계의 상한선에 근접한 디스크는 더 이상 데이터를 받을 수 없다고 커널에 알리기 시작하며 iowait를 유발하고, 커널은 들어오는 데이터를 메모리의 더티 쓰기 풀(dirty write pool)에 큐잉해요. 그러나 vmstat(1)과 free(1)를 사용해 스왑이 사용되지 않고 있고 디스크 IO가 초당 몇 킬로바이트에 불과하다는 것을 확인할 수 있었어요.
높은 프로세서 사용으로 인한 느림
다음으로 시스템이 단순히 매우 높은 계산 부하 때문에 느리게 수행되는지 확인했어요. top(1)은 시스템 로드가 평소보다 높음을 보여줬지만, vmstat(1)과 mpstat(1)은 실제 계산에 사용되는 프로세서 양이 적음을 보여줬어요.
네트워크 포화 (우승자) (Network Saturation (The Winner))
디스크도 프로세서도 많이 사용되지 않았으므로 네트워크 인터페이스의 성능으로 넘어갔어요. DataNode에는 active-standby 인터페이스를 형성하도록 본딩된 기가비트 이더넷 어댑터 두 개가 있었어요. ifconfig(8)은 몇 가지 비정상적인 이상 징후, 즉 인터페이스 오류, overrun, 프레이밍 오류를 보여줬어요. 이와 같은 오류는 전혀 들어본 적 없는 것은 아니지만, 제대로 작동하는 현대 하드웨어에서는 극히 드물어요.
$ /sbin/ifconfig bond0 bond0 Link encap:Ethernet HWaddr 00:00:00:00:00:00 inet addr:10.x.x.x Bcast:10.x.x.255 Mask:255.255.255.0 UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1 RX packets:2990700159 errors:12 dropped:0 overruns:1 frame:6 <--- Look Here! Errors! TX packets:3443518196 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2416328868676 (2.4 TB) TX bytes:3464991094001 (3.4 TB)
이 오류들은 하나 이상의 이더넷 인터페이스가 잘못된 라인 속도로 협상(negotiate)됐을 수 있다는 의심을 즉시 갖게 했어요. 외부 호스트에서 ICMP ping을 실행해 700ms를 초과하는 왕복 시간을 관찰하고, 본드 인터페이스의 멤버에 ethtool(8)을 실행해 활성 인터페이스가 100Mbs, full duplex로 작동 중이라는 것을 발견함으로써 이 가설이 확인됐어요.
$ sudo ethtool eth0 Settings for eth0: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Advertised pause frame use: No Advertised auto-negotiation: Yes Link partner advertised link modes: Not reported Link partner advertised pause frame use: No Link partner advertised auto-negotiation: No Speed: 100Mb/s <--- Look Here! Should say 1000Mb/s! Duplex: Full Port: Twisted Pair PHYAD: 1 Transceiver: internal Auto-negotiation: on MDI-X: Unknown Supports Wake-on: umbg Wake-on: g Current message level: 0x00000003 (3) Link detected: yes
정상 동작에서 ICMP ping 왕복 시간은 약 20ms여야 하고, 인터페이스 속도와 duplex는 각각 "1000MB/s"와 "Full"로 읽혀야 해요.
해결 (Resolution)
활성 이더넷 어댑터가 잘못된 속도에 있다는 것을 확인한 뒤 ifenslave(8) 명령으로 standby 인터페이스를 활성 인터페이스로 만들었어요. 이는 MapReduce 성능의 즉각적인 개선과 네트워크 처리량의 10배 개선을 가져왔어요.
다음에 데이터센터에 방문했을 때, 라인 속도 문제가 궁극적으로 불량 네트워크 케이블 때문임을 확인했고 이를 교체했어요.
케이스 스터디 #2 (2012 성능 연구) (Case Study #2 (Performance Research 2012))
"무엇이 잘못됐는지 모르겠지만 느려 보인다"고 스스로 표현한 문제에 대한 조사 결과예요. http://gbif.blogspot.com/2012/03/hbase-performance-evaluation-continued.html
케이스 스터디 #3 (2010 성능 연구) (Case Study #3 (Performance Research 2010))
2010년 일반 클러스터 성능의 조사 결과예요. 이 연구는 코드베이스의 구버전에 대한 것이지만, 이 글은 접근 방식 측면에서 여전히 매우 유용해요. https://web.archive.org/web/20180503124332/http://hstack.org/hbase-performance-testing/
케이스 스터디 #4 (max.transfer.threads 설정) (Case Study #4 (max.transfer.threads Config))
max.transfer.threads(이전 이름 xcievers)를 설정하고 잘못된 설정으로 인한 오류를 진단하는 케이스 스터디예요. http://www.larsgeorge.com/2012/03/hadoop-hbase-and-xceivers.html
또한 dfs.datanode.max.transfer.threads를 참고하세요.