Tag Archives: Hector

[NoSQL/Cassandra] Java용 가장 유명한 클라이언트 Hector 소개

사용자 삽입 이미지

Introduction

그리스 신화에서 카산드라의 형제로 나오는 헥터(Hector)는 가장 위대한 전사였고 트로이를 건설한 인물로 묘사됩니다. 하지만 현재의 IT세계에서는 이둘을 확장성이 뛰어난 데이터베이스와 여기에 쓰이는 자바 클라이언트 라이브러리에 이름을 붙였군요. 실제로 Cassandra를 사용함에 있어 자바를 선택하셨다면 가장 범용적으로 사용되는 라이브러리가 바로 이 Hector입니다. 가장 꾸준히 업그레이드 되고 있고 레퍼런스 역시 잘 구축되어있습니다.

지금까지 나온 다양한 Raw Thrift 클라이언트들은 대체적으로 실제의 클라이언트가 요구하는 필수적인 기능들은 부족한 상황입니다. 이러한 갭을 채우기 위해서 Hector를 만들었습니다.

Cassandra를 위한 하이 레벨 객체 지향 인터페이스를 제공합니다. 기존의 클라이언트들은 항상 멋지고 깔끔한 작업이 가능하도록 하지는 못했습니다. 좀 더 높은 레벨의 깔끔한 API를 제공하는 자바 클라이언트가 바로 이 Hector입니다.

Hector는 Failover를 지원합니다. Cassandra는 데이터를 분산하여 저장하며 어떤 경우에는 매우 잘 동작하겠지만 하나의 노드 또는 다수의 노드가 다운될 수 있습니다. 그러나 기존의 Thrift는 이러한 문제에 아무런 처리를 제공하지 않습니다. 그러나 Hector는 특정 노드가 죽을 경우 자동으로 실패한 명령을 수행할 수 있는 사용가능한 다른 호스트를 검색하고 사용자에게 에러를 알립니다. Failover 를 위한 3가지 정책을 제공하는데 FAIL_FAST(재시도 없음, 에러 발생시 바로 실패, 스마트하지 않음), ON_FAIL_TRY_ONE_NEXT_AVAILABLE(포기하기전에 다른 호스트에 한번 더 시도), ON_FAIL_TRY_ALL_AVAILABLE(포기하기 전에 모든 호스트에 시도)를 제공합니다.

Hector는 커넥션 풀링을 제공합니다. 이 기능은 대규모 어플리케이션에 필수적인 부분입니다. 이런 어플리케이션은 일반적으로 사용되는 DAO패턴을 통해 엄청난 횟수의 작은 규모의 읽기/쓰기가 발생합니다. 클라이언트들은 매번의 요청에 대해 새로운 커넥션을 열만큼의 여력을 가지지 못합니다(TCP 핸드쉐이크 오버헤드). 이에 Hector는 커넥션풀링을 제공하며 매우 멋진 프레임워크 입니다.

Hector는 JMX를 지원하면 이를 이용해서 실행 레벨에서 Metric, 사용가능한 커넥션 수, 유휴 커넥션수, 에러통계등의 정보를 가져올 수 있습니다. Hector는 Command 디자인패턴을 지원하며 사용자는 자신의 비지니스 로직에만 집중할 수 있도록 설계되어있습니다.

Getting Started (5 minutes)

Fully Mavenized
이 저장소를 사용하기 위해서는 다음의 의존성 선언을 당신의 POM파일에 추가하십시오
[code]<dependency>
    <groupId>me.prettyprint</groupId>
    <artifactId>hector-core</artifactId>
    <version>0.8.0-2</version>
</dependency>[/code]
Initializing a Cluster
이제 처음으로 Cassandra 클러스터를 나타내는 클러스터 객체를 생성할 것입니다. 여기서 정의하는 클러스터 이름은 Hector에서 식별하기 위해 사용되며 실제 클러스터의 이름과는 무관합니다. 코드를 좀더 깔끔하게 보이기 위해 API 패키지 전체를 임포트 하였습니다.
[code]import me.prettyprint.hector.api.*;
    …..
Cluster myCluster =
    HFactory.getOrCreateCluster(“test-cluster”,”localhost:9160″);[/code]
스키마를 정의해 봅시다.
[code]ColumnFamilyDefinition cfDef =
HFactory.createColumnFamilyDefinition(
“MyKeyspace”,
“ColumnFamilyName”,
ComparatorType.BYTESTYPE);

KeyspaceDefinition newKeyspace =
HFactory.createKeyspaceDefinition(
“MyKeyspace”,                
ThriftKsDef.DEF_STRATEGY_CLASS,  
replicationFactor,
Arrays.asList(cfDef));

// 클러스터에 스키마 추가
// 두번째 파라미터인 “true”는 모든 클러스터에 변화가 완료될때까지 블록이 됨을 의미
cluster.addKeyspace(newKeyspace, true);[/code]
한번 스키마가 생성되고 나면 이전의 호출은 스키마가 이미 존재함을 알리는 예외를 발생시킵니다. 이 문제를 해결하기 위해서 위의 코드를 createSchema()라는 메소드로 래핑하여 다음과 같이 변경하였습니다.
[code]KeyspaceDefinition keyspaceDef = cluster.describeKeyspace(“MyKeyspace”);

// Keyspace가 존재하지 않는다면 생성합니다.
if (keyspaceDef == null) {
    createSchema();
}[/code]
이제 생성된 Keyspace를 다음과 같은 명령으로 꺼내 쓸 수 있게 되었습니다. “MyKeySpace”는 반드시 이전에 생성된 Keyspace여야 합니다.
[code]Keyspace ksp = HFactory.createKeyspace(“MyKeyspace”, myCluster);[/code]

Creating a template
템플릿은 Keyspace를 조작하기 위한 객체입니다. 이론적으로 비지니스 로직에 대한 접근을 용이하게 하기 위해 사용됩니다.
[code]import me.prettyprint.cassandra.service.template.ColumnFamilyTemplate;
    ……
ColumnFamilyTemplate<String, String> template =
new ThriftColumnFamilyTemplate<String, String>(
ksp,
columnFamily,
StringSerializer.get(),        
StringSerializer.get());[/code]
Accessing data
* Update
[code]// <String, String> 는 키와 값을 뜻함
ColumnFamilyUpdater<String, String> updater =
    template.createUpdater(“a key”);
updater.setString(“domain”, “www.datastax.com”);
updater.setLong(“time”, System.currentTimeMillis());

try {
    template.update(updater);
} catch (HectorException e) {
    // do something …
}[/code]
* Read
[code]try {
    ColumnFamilyResult<String, String> res =
        template.queryColumns(“a key”);
    String value = res.getString(“domain”);
    // 이전에 저장했던 “www.datastax.com” 가 반환됨
} catch (HectorException e) {
    // do something …
}[/code]
* Delete
[code]try {
    template.deleteColumn(“key”, “column name”);
} catch (HectorException e) {
    // do something
}[/code]

참고 :
http://prettyprint.me/2010/02/23/hector-a-java-cassandra-client/ 
https://github.com/rantav/hector/wiki/Getting-started-%285-minutes%29
https://github.com/rantav/hector/downloads  (다운로드)

[NoSQL/Java] Cassandra 클라이언트 퍼포먼스 비교 (Pelops/Hector/Kundera)

Java용으로 쓸만한 Cassandra 클라이언트 라이브러리를 찾다보니 대충 Pelops, Hector, Kundera정도로 나뉘어 지는것 같더군요. 셋중에 무엇이 가장 좋은가를 놓고 비교해 보자면 다양한 결론이 나오겠지만 Kundera에서 자체적으로 내놓은 퍼포먼스 테스트 결과가 있습니다. 퍼포먼스만 달랑 놓고 보면 Kundera가 가장 떨어지는 결과를 보여주니 일부러 거짓말 하는 데이터는 아닌것 같아 보입니다.

Kundera Performance 발번역

Kundera의 퍼포먼스를 Hector / Pelops와 비교해 보았습니다. 왜 Hector / Pelops인가요? Kundera는 데이터 저장소에 객체를 매핑해주는 툴이고 Hector / Pelops는 하이 레벨의 Cassandra 클라이언트입니다. 그렇기 때문에 이 비교는 논란이 될 수 있습니다. 이 비교의 의도는 Kundera 가 추가적으로 제공하는 매핑이나 다른 멋진 기능들의 오버헤드가 얼마나 되는지 계산해 보기 위함입니다.

Kundera – Cassandra는 Lucene기반의 인덱싱을 제공하며 그렇기 때문에 Hector/Pelops가 할수 있는 것들외에 추가적인 작업이 가능합니다. 그러므로 테스트는 이 Lucene인덱싱을 사용할때와 안할때 두가지 시나리오를 가지고 진행됩니다. 전자는 이 추가적인 인덱싱 기능을 사용하지 않으므로 비교해볼만한 상대가 될지 모르겠지만 후자의 경우에는 인덱싱을 내장 지원하기 때문에 비교대상이라 보기 어려운 퍼포먼스를 보여주긴 합니다.

Kundera Without Indexing Support

Bulk Load:

Number Of Records
(Single Thread)
Pelops Time
(in ms)
Hector Time
(in ms)
Kundera
(in ms)
1 22 56 82
1000 550 666 925
4000 1791 1928 2952
40000 10533 10645 12392
100000 23832 24675 25994
1000000 221154 229619 236242

Concurrent Load:

Number Of Threads
(1 record)
Pelops Time
(in ms)
Hector Time
(in ms)
Kundera
(in ms)
10 53 57 80
100 232 259 250
1000 1560 1443 1718
10000 9120 8514 10127
40000 28869 28330 29506
50000 36454 34823 36336
100000 68586 65513 69513

Concurrent Load + Bulk Load:

Number Of Threads
(1000 rec/ thread)
Pelops Time
(in ms)
Hector Time
(in ms)
Kundera
(in ms)
10 3968 4434 5085
100 21560 22329 25274
1000 227232 207834 226541

Kundera With Indexing Support

Bulk Load:

Number Of Records
(Single Thread)
Pelops Time
(in ms)
Hector Time
(in ms)
Kundera
(in ms)
1 25 40 93
1000 677 957 1719
4000 2131 2429 3901
40000 13009 13075 22158
100000 28884 30097 44876
1000000 256986 262067 375137

Concurrent Load:

Number Of Threads
(1 record)
Pelops Time
(in ms)
Hector Time
(in ms)
Kundera
(in ms)
10 53 56 118
100 232 281 552
1000 1560 1823 2762
10000 9120 9776 14104
40000 28869 32331 39549
50000 36454 37172 50099
100000 68586 74304 95410

Concurrent Load + Bulk Load:

Number Of Threads
(1000 rec/ thread)
Pelops Time
(in ms)
Hector Time
(in ms)
Kundera
(in ms)
10 4343 4738 9546
100 26010 24619 35196
1000 227232 219247 308975


위의 단순한 결과들로만 보면 Kundera는 모든 면에서 다른 라이브러리에 비교해 뒤쳐지는 속도를 보여줍니다. 하지만 Kundera는 Lucene인덱싱 POJO에 직접적인 데이터 매핑등 사용상에 많은 장점을 가지고 있습니다. 대충 검색해 보았을때는 Kundera는 Full-Text 검색도 지원한다고 합니다. 사실상 NoSQL에서 지원하기 어려운 점들입니다. 사용해 보진 않았지만 다양한 기능을 제공하는것으로 보여집니다.

참고: https://github.com/impetus-opensource/Kundera/wiki/Kundera-Performance