사용환경
- Hadoop 0.20.2
- Hbase 0.20.6
- ext library : tableIndexed library for hbase0.20.6
- fully-distributed setup
1. hbase 설치
http://hbase.apache.org 에서 0.20.6 버전을 다운로드 받아 설치한다.
(현재 0.90.x가 나오고 있지만 아직 rc버전이다.)
* 명심할것은 Hbase의 위치는 마스터또는 슬레이브서버 모두 동일해야 한다.
서로 동일한 패스에 위치해야한다는 것을 명심하자.
2. /etc/host에 다음을 등록하자.
* localhost에 127.0.0.1 같이 설정하지 마라
* hostname에 - 같은 것을 쓰지마라. 인식을 할수 없다.
http://en.wikipedia.org/wiki/Hostname
192.168.0.202 localhost
192.168.0.203 hadoop.master
192.168.0.203 hadoop.slave
192.168.0.202 hbase.master
192.168.0.203 hbase.slave
- hadoop.slave : hadoop 슬레이브 서버의 위치
- hbase.master : hbase 마스터 서버의 위치
- hbase.slave: hbase 슬레이브 서버의 위치
3. 환경 설정 (마스터, 슬레이브 서버 공통)
* hbase_env.sh 설정에 추가
- jdk home path 설정 추가
- table indexed 라이브러리를 사용하는 사람은 아래를 추가한다.
(해당 외부 라이브러리 필요없으면 아래작업이 필요없다.)
export EXT_CLASSPATH=${HBASE_HOME}/lib/hbase-0.20.6-transactional.jar;
export HBASE_CLASSPATH=${EXT_CLASSPATH}
4. hbase-site 설정( Master, Slave 서버 공통)
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- Hadoop 의 Master 서버접속 url을 기록한다. -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop.master:9000/hbase</value>
</property>
<!-- Hbase의 마스터 서버 위치를 설정한다. 현재 이서버가 해당된다. -->
<property>
<name>hbase.master</name>
<value>hbase.master:60000</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
<description>The mode the cluster will be in. Possible values are
false: standalone and pseudo-distributed setups with managed Zookeeper
true: fully-distributed with unmanaged Zookeeper Quorum (see hbase-env.sh)
</description>
</property>
<!-- 아래는 indexed 외부 라이브러리가 필요한 사람만 추가로 등록한다. -->
<!-- Secondary Indexes in Habase. -->
<property>
<name>hbase.regionserver.class</name>
<value>org.apache.hadoop.hbase.ipc.IndexedRegionInterface</value>
</property>
<property>
<name>hbase.regionserver.impl</name>
<value>org.apache.hadoop.hbase.regionserver.tableindexed.IndexedRegionServer</value>
</property>
</configuration>
5. 마스터 서버에 추가 설정 (슬레이브 서버는 하지 않는다.)
conf 폴더에 regionservers 파일을 생성하고
hbase.master
hbase.slave
를 등록한다.
6. 서비스 실행
이제 설정이 모두 완료되었다.
마스터 서버에서 ./start-hbase.sh 를 하면 아래와 같이 자동적으로 Slave 서버까지 자동으로 구동될것이다. (마스터 서버에서만 실행하는것을 명심하자)
* 마스터 서버에서
./start-hbase.sh
# jps로 확인시 아래와 같은 서비스가 구동되어 있으면 성공이다.
- 마스터
HRegionServer
HQuorumPeer
- 슬레이브
HRegionServer
추가)
Hbase가 비록 BigTable같이 좋은 아키텍쳐를 지니고 있지만, 사용성 면에서는 많이 떨어지더군요. 그래서
http://code.google.com/p/hbase-jdo/ 같은 오픈소스 프로젝트를 만들어 진행중입니다. 도움이 되었으면 하는군요. 이 프로젝트안에 있는 툴로 Hbase, Hadoop을 쉽게 조회 해볼 수 있으니 한번 사용해 보세요.
shell 실행
$ bin/hbase shell
7. Test
Test an Example Program
Original program source : http://hadoop.apache.org/hbase/docs/current/api/overview-summary.html#overview_description
sample/MyClient.java
package samplebuild.xml
import java.io.IOException;import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Scanner;
import org.apache.hadoop.hbase.io.BatchUpdate;
import org.apache.hadoop.hbase.io.Cell;
import org.apache.hadoop.hbase.io.RowResult;public class MyClient {
public static void main(String[] args) throws IOException {
// 클라이언트에서 어디로 접속할지 설정 객체에게 알려야 한다.
// 기본으로 로컬 설정 파일에서 해당 정보를 가지고 오니 걱정하지는 말자.
HBaseConfiguration config = new HBaseConfiguration();
// 'myTable' 테이블에 접속하는 HTable 객체를 생성한다.
HTable table = new HTable(config, "myTable");
// row에 대한 모종의 업데이트를 수행하기 위해서는 BatchUpdate 객체를 사용한다.
// BatchUpdate는 row 하나와 옵션으로 timestamp 값을 받는다.
BatchUpdate batchUpdate = new BatchUpdate("myRow");
// BatchUpdate의 put() 메소드는 값을 넣은 셀을 기술하는 텍스트와
// 저장하고자 하는 값이 있는 byte 배열을 인자로 받는다.
// 따라서 String이나 다른 primitives등을 저장하고자 한다면 getBytes()를 사용해야한다.
batchUpdate.put("myColumnFamily:columnQualifier1", "columnQualifier1 value!".getBytes());
// HBase에서는 삭제도 배치 작업이다.
//batchUpdate.delete("myColumnFamily:cellWantDeleted");
// 작업을 끝낸 뒤에는 결과를 commit 한다.
// HTable#commit 메소드는 BatchUpdate 객체를 인자로 받아 배치작업을 수행한다.
table.commit(batchUpdate);
// 이제 방금 저장한 값들을 읽어보자. 리턴되는 값은 Cell 객체이다.
// Cell은 byte 배열로 이루어진 값과 timestamp 값의 조합이다.
Cell cell = table.get("myRow", "myColumnFamily:columnQualifier1");
String valueStr = new String(cell.getValue());
// 찾고자 하는 row를 모를 경우, Scanner를 사용한다. Scanner는 테이블의 내용에 대한
// cursor 스타일의 인터페이스를 제공한다.
Scanner scanner = table.getScanner(new String[]{"myColumnFamily:columnQualifier1"});
// HBase 0.2에 있는 Scanner는 RowResult 객체를 리턴한다.
// RowResult는 row key와 column들을 하나의 인터페이스로 묶어놓은 것과 같다.
// RowResult#getRow는 row key를 리턴한다.
// 또한 RowResult는 Map 인터페이스를 구현해두고 있기 때문에 column 결과에 쉽게 접근 가능하다.
RowResult rowResult = scanner.next();
while (rowResult != null) {
System.out.println("Found row: " + new String(rowResult.getRow()) + " with value: " + rowResult.get("myColumnFamily:columnQualifier1".getBytes()));
rowResult = scanner.next();
}
// iterable한 Scanner를 foreach로 탐색하는 방법도 있다.
for (RowResult result : scanner) {
System.out.println("Found row: " + new String(result.getRow()) + " with value: " + result.get("myColumnFamily:columnQualifier1".getBytes()));
}
// 작업이 끝나면 Scanner를 닫도록 한다.
scanner.close();
}
}
<project name="MyClient">[hadoop@master example]$ ls
<property name="target.dir" value="build" />
<property name="classes.dir" value="${target.dir}/classes" />
<property name="source.dir" value="src" />
<property name="lib.dir" value="lib" />
<target name="init">
<mkdir dir="${classes.dir}" />
<path id="build.classpath">
<fileset dir="${lib.dir}">
<include name="**/**.jar" />
</fileset>
</path>
</target>
<target name="compile" depends="init">
<javac
srcdir="${source.dir}"
destdir="${classes.dir}"
classpathref="build.classpath"
encoding="utf-8"
/>
</target>
</project>
build.xml lib src
[hadoop@master example]$ ant compile
...
[hadoop@master example]$ ls
build build.xml lib src
[hadoop@master example]$ cd build/classes
[hadoop@master example]$ ls
sample
[hadoop@master classes]$ export HBASE_HOME=/home/hadoop/hbase
[hadoop@master classes]$ $HBASE_HOME/bin/hbase sample.MyClient
Found row: myRow with value: timestamp=1217998267705, value=columnQualifier1 value!