hbase 0.90 버전부터는 hadoop의 append 기능을 이용하고 있습니다. hadoop 0.20 정식 릴리즈 버전에서는 append 기능을 제공하지 않기 때문에 hbase의 lib에 있는 hadoop-core-0.20-append-r1056497.jar 파일로 hadoop의 jar 파일을 대체하여 재시작해야 합니다. 이것 말고 주의해야 할 부분이 하나 더 있는데 append 모드를 사용하기 위해서는 dfs.support.append 설정 값을 true로 설정해야 합니다. 이 설정이 dfs의 설정이다 보니 hadoop의 conf/hdfs-site.xml 파일에만 설정하는 경우가 있는데 이렇게 하면 Configuration 객체가 dfs.support.append 값을 로딩하지 못하여 append 기능을 사용하지 않는 모드로 동작하게 됩니다. Configuration 클래스의 경우 기본 생성자에서는 core-default.xml, core-site.xml 만 로딩하고 별도로 hdfs-default.xml, hdfs-site.xml, mapred-default.xml, mapred-site.xml 을 로딩하기 위해서는 addResource 메소드를 호출해야 합니다. hbase 코드 상에서 dfs.support.append 값을 읽어 오기 위해 Configuration 객체를 사용합니다. 따라서 dfs.support.append 값을 인식하게 하기 위해서는 hbase의 conf/hbase-site.xml 파일에 설정하거나 hadoop의 conf/core-site.xml에 설정해야 합니다. 그리고 append 기능 및 sync 기능을 이용한다고 해서 WAL 로그가 sync호출 즉시 hdfs에 반영되는 것은 아닙니다. hadoop-0.20-append 버전에서의 sync 메소드를 호출한다고 해서 hdfs 파일에 바로 반영되는 것은 아닙니다. 이 기능은 hadoop-0.21에 적용되어 있습니다. hadoop-0.20.append 관련 소스는 hadoop의 common branch에 있습니다. 참고하세요.
hadoop을 수년간 운영해왔지만 hadoop monitoring metrics 데이터를 자세하게 보지는 않았습니다. 특정 서버 장애는 서비스 운영에 크게 문제가 되지 않았기 때문이죠. 최근 파일이 많아지고 사용량이 많아지면서 일부 서버에 장애가 지속적으로 발생하여 계속 모니터링 해보고 있습니다. cloumon-enterprise를 이용해서 메모리 상황을 모니터링 해 보았습니다. namenode 쪽은 파일으 급격하게 증가하지는 않기 때문에 안정적인 패턴을 보이고 있습니다. 현재 File, Block 갯수는 4백만개 정도 됩니다. 아래 그림에서 보듯이 600 ~ 700 MB 정도 사용하고 있습니다.
[그림] namenode heap usage
DataNode 쪽은 메모리에 대해서는 별로 신경쓰지 않았는데 cloumon 적용하면서 확인해보니 의외로 많이 사용하고 있었습니다. 아마 블럭 정보를 메모리에 모두 올려 관리하기 때문이 아닌가 생각합니다. 첫번째 그림의 DataNode는 블럭을 50만개 정도 가지고 있는 서버이고 두번째 서버는 13만개 블럭을 가지고 있는 서버입니다. 메모리 사용량은 500MB, 200MB 정도입니다.
hadoop이 지난달 0.21로 업그레이드 되면 append 기능이 추가되었습니다. append에 대해 성능 테스트를 수행해 보았는데 결과 공유합니다.
테스트를 수행한 환경이 VM환경이라 절대적인 성능 수치 보다는 일반 write와 속도 비교가 더 의미 있을 겁니다. 그리고 부하 상황이 아닌 싱글 클라이언트 상황에서의 테스트입니다.
1. 테스트 환경 . 물리적 서버 3대, 각 서버에 VM5대 . Hadoop 1 master, 23 datanode . Hadoop 버전: 0.21
2. 테스트 프로그램 . 1024 bytes를 102,400번 수행 -> 100MB . 별첨 참고
3. 테스트 결과 . write(BufferedOutputStream 사용시): 17,654 ms . write(DFSOutputStream 사용시): 12,298 ms . append(DFSOutputStream 사용시, 매번 flush 호출): 130,436 ms . append(DFSOutputStream 사용시, 마지막에 flush 호출): 11,398 ms . append(DFSOutputStream 사용시, 1000건 단위로 flush 호출): 16,225 ms
4. 결론 . append의 경우 flush()를 호출하지 않으면 기존 write의 동일한 성능 . append 연산을 사용하는 용도가 주로 로그 데이터 저장 등인데 이 경우 매번 flush 해주는 경우가 일반적 -> 이런 상황에서는 10배 정도의 성능 저하 발생 . append 도중 close를 하지 않은 상태에서 클라이언트가 강제 종료되면 일전 시간(수 분) 내에서는 파일 읽기 연산 불가
. append 사용 가능 상황 -> 쓰기 시간이 중요하지 않고 중요한 데이터 -> 쓰기 시간이 중요하지만 일부 데이터(1000건 정도) 유실이 발생해도 무방한 데이터
Hadoop의 DataNode에서 여러개의 볼륨을 사용할 경우 하나의 볼륨에만 문제가 있어도
데이터 노드 자체가 죽어버려 정상적인 디스크에 있는 데이터까지 모두 복구 작업이 진행된다.
소스를 보니 다음 코드처럼 구현되어 있으니 당연히...
/* Check if there is no disk space and if so, handle the error*/
protected void checkDiskError( ) throws IOException {
try {
data.checkDataDir();
} catch(DiskErrorException de) {
handleDiskError(de.getMessage());
}
}
private void handleDiskError(String errMsgr) {
LOG.warn("DataNode is shutting down.\n" + errMsgr);
shouldRun = false;
try {
namenode.errorReport(
dnRegistration, DatanodeProtocol.DISK_ERROR, errMsgr);
} catch(IOException ignored) {
}
}
HICC(Hadoop Infrastructure Care Center)는 chukwa의 서브 모듈로 탑재 되어 있으며 하둡 클러스터를 모니터링 하는 화면을 제공한다. 지난번에 한번 실패하고 이번에 다시 도전해서 성공... 지난번에도 성공헀었는데 화면단에서 조회 조건에서 GMT+0 기준으로 데이터 조회하고 있는 바람에 데이터가 나타나지 않았다는 ㅋㅋㅋ
클라이언트에서 파일 저장 시 hadoop의 블럭 복제 방법에 대해 질문하셨는데 다음과 같은 순서로 진행됩니다.
1. 클라이언트는 NameNode에게 블럭 전송을 시작한다고 알린다.
2. NameNode는 적절한 데이터노드 3개를 선택해서 클라이언트로 보낸다.
3. 클라이언트는 첫번째 데이터노드로 전송할 데이터를 보낸다.
4. 데이터노드는 받은 데이터를 두번째 노드로 전송하고 자신의 디스크에 기록한다.
5. 그 다음 데이터노드도 동일한 방법으로 수행한다.
6. 64MB 블럭을 전송하고 나면 1번 부터 다시 시작한다.
이상입니다.
3 카피를 저장하는데 속도가 3배로 더 소요되지 않고 조금 더 소요되는 것은 Client -> DataNod1 -> DataNode2 -> DataNode3 와 같이 전송 패킷 단위로 파이프라인되기 때문이라고 보시면 됩니다. 2 ~ 3번째 데이터노드에서 패킷을 처리하는 동안 첫번째 데이터노드는 다음번 패킷을 받기 때문입니다.
그리고 이런 글은 비밀 댓글로 하지 않으셔도 됩니다. 다른 분들에게도 같이 공유하면 좋겠죠. ㅋㅋ
먼저 성의있는 답변감사드립니다.
블럭 복제 과정에서 datanode1 이 client 에서 블럭을 받을때 지연 없이 최대 대역폭으로 블럭을 다운로드 하고 있다면, datanode2 에게 파이프라인으로 전송을 하더라도 역시 같은 네트워크 라인에 이용할 대역폭이 없기 때문에 속도가 더욱 지연될거라고 생각하거든요. 파이프라인도 결국은 네트워크 라인을 사용하기 때문에 이런 고민을 하게 되었습니다.^^
네트워크 기반이기 때문에 네트워크 대역폭이상으로 성능이 나올수는 없겠죠. 다만 기존에 중앙집중되어 있는 스토리지(NAS, SAN)등에 비해 분산된 서버를 이용하기 때문에 네트워크도 트래픽도 분산되는 효과를 볼수 있습니다.
이것도 업링크에 부하가 집중되면 어쩔수 없고요... 하둡 구성시 가장 신경써야 하는 부분이 바로 이런 부분입니다. 내부용으로 사용할 경우는 문제가 안되지만 저장된 파일을 이용하여 외부 서비스를 하는 경우 신경써야 하는 부분입니다.
하둡 책을 읽으면서 궁금하게 생각한 부분이었는데요. 20개의 데이터노드를 활용할 수 있다고 가정할때 2개의 랙으로 10개 노드씩 구성하는것과 하나의 랙에서 20개 노드로 구성하는 것이 전자가 더 장점을 갖을 수 있는 부분이 위와같은 경우인가요? 단순하게 생각하면 같은 랙 안의 노드끼리 전송속도가 더 빠르다고 생각되서 더 좋을 것 같다고 느껴지는데요...2개의 랙으로 나눠서 구성했을때의 장점이 무엇인지가 궁금합니다.
안녕하세요. 랙 분리와는 상관없는 것 같습니다.
서로 다른 랙이라도 스위치 하나에 연결되어 있으면 dedicated GB를 보장받으니까 문제되지는 않을 겁니다.
랙에 스위치가 같이 있어서 랙-랙간에는 업링크를 타게 되면 하나의 랙에 두는 게 좋고요... 따라서 이것은 랙의 문제라기 보다는 스위치 구성의 문제입니다.
랙을 분리하면 좋은 것은 장애가 발생하는 단위가 랙 단위로 발생할 가능성이 많기 때문에 rack awareness 기능을 이용해서 하나의 랙에 장애가 발생해도 동일 블럭이 다른 랙의 노드에 있도록 할 수도 있습니다.
랙을 나누면 IDC의 랙당 운영 비용이 올라가는 단점도 있을 겁니다.
Pig, Hive는 목적은 동일합니다. 하둡에 저장된 데이터를 프로그램이 아닌 스크립트 언어로 쉽게 분석해보자는 것입니다.
가장 큰 차이는 물론 스크립트 문법이겠죠... Pig는 좀 더 많은 프로그램적인 요소가 들어가 있어 조금 복잡하지만 기능적으로는 더 풍부하다고 할 수 있습니다. Hive는 SQL 비슷해서 쉽게 사용할 수 있는 장점이 있죠...
두번째 차이점은 Pig는 모든 하둡 파일을 이용할 수 있지만 Hive는 테이블 개념이 들어 있습니다. Hive는 테이블을 생성하고 테이블에 데이터를 넣는 방식입니다. 테이블리라고 해서 거창한 것은 아니고 컬럼 정도만 정의 되어 있고 파일을 저장할 때 Hive 명령을 이용해서 저장하면 해당 컬럼에 맞게 구분자를 추가해서 저장하는 정도입니다.
안녕하세요. owner 에러 나타난 것은 소스를 봐야 정확하게 알 것 같습니다. 아마 chukwa가 하둡에 특정 디렉토리를 만들어서 그곳에 위젯 정보 등을 저장하고 사용하는데 그것때문이지 않나 생각이 듭니다.
포트 문제는 chukwa의 경우 collector와 hicc 웹 서버를 같은 서버에 실행하지 않습니다. 같이 실행할 경우 hicc port를 변경하거나 collector port를 변경합니다. 이때 agent에서도 변경된 포트를 인식하게 하기 위해서 conf/collectors 파일을 수정하시면 됩니다.
Appistry explains that the native HDFS architecture is built around a single metadata repository called the NameNode and because the NameNode isn't easily clustered, it represents a single point of failure and a bottleneck for the entire system. CloudIQ Storage fixes that limitation.
Hadoop 0.20 잠깐 봤는데 MapReduce 클래스가 모두 바뀌었네요. 기존에는 org.apache.hadoop.mapred 패키지였는데 org.apache.hadoop.mapreduce 라는 패키지가 만들어져 있고 기존의 org.apache.hadoop.mapred 패키지 대부분 클래스는 deplicate 되었습니다. Mapper 클래스도 기존의 configuration(), map(), close()가 아니라 setup(), map(), cleanup()으로 바뀌었네요. 기타 많이 바뀌었지만 일단 hadoop-0.20과 호환 가능하도록 Neptune의 MapReduceUtil 클래스를 조정해야 겠습니다. 아직 1.0은 아니라고 하지만 너무 심한 변화네요.