-
O'REILLY HBASE 완벽가이드를 보고 따라한 내용
2018/07/17 - [2018년 상반기/DataBase] - 험난한 HBASE 설치기
로 HBASE 설치를 완료했다. 이제 책을 보고 공부할 수 있게 되었다 ^-^
들어가기 전에,,,
1) row 단위의 작업은 원자성이 보장된다. 즉, 읽을때는 항상 일관성이 보장되어 최신 데이터를 읽을 수 있고 쓰기 시도를 할때는 기다려야 한다.
-8장에서 다룰 내용이다.
2) HTable 인스턴스를 생성하는 일에는 비용이 든다. 메타 테이블을 스캔해서 HTable이 지정하는 테이블이 존재하고 활성화되어있는지 확인하고 그 외에 작업을 좀 더 수행하기때문이다. 그러니 당연히 인스턴스는 한번만 그리고 스레드당 하나씩만 만들어서 재사용을 하는게 좋다.
3) 그래도 인스턴스가 많이 필요하다면 HTablePool을 쓰면 된다.
-4장에서 다룰 내용이다.
CRUD(Create,Read,Update,Delete) 기능
1. Put 메서드 (단일로우대상/멀티로우대상)
1.단일 Put
void put(Put put) throws IOException
Put 객체는 아래와 같이 hbase의 객체로서 아래와 같은 방법들로 생성할 수 있다.
API 문서 https://hbase.apache.org/2.0/apidocs/index.html
*책에서는 RowLcok 객체를 넘겨줘서 생성할 수 있다는데,, API를 조사해보면 다음과 같이 이제 사용하지 않는다. 책의 HBASE 버전이 좀 오래 되었다.
위에를 보면 생성할 때에 byte[ ] 타입을 넘겨주어야 한다. (byte 배열) HBASE의 row는 row key로 식별되고 이들은 바이트 배열 타입이다.(HBASE에서는 대부분 byte[] 타입이라고 한다.) - key를 설계하는 방법은 9장에서 설명한다.
아래와 같이 hbase에서는 byte[ ]로 변환해주는 클래스를 제공한다.
Put 인스턴스를 생성하면 이 인스턴스에 아래의 메서드를 사용하여 데이터를 추가할 수 있다.
add(Cell cell)을 보면 KeyValue를 추가한다고 되어있다. KeyValue 클래스는 하나의 고유한 Cell을 나타낸다.
Put은 Mutation을 상속받고 있다. 그래서 Mutation에 존재하는 method를 보자면 아래와 같이 여러가지의 메서드들이 존재한다.
이중에서 소개된 것을 보자면 get Class KeyValue type 인스턴스를 얻을 수 있다.
has라는 메서드는 사용하면 특성 Cell이 존재하는지에 대하여 알 수 있다.api는 이쯤 봐두고 무작정 그냥 사용해보자. 우선 실행하기에 앞서, 메이븐을 설치해주고 다음과 같은 폴더 구성을 해준다.
pom.xml은 메이븐을 위한 디펜던시를 작성하기 위한것이고, src/main/java 아래에 코드를 작성할 java 파일을 넣어준다.
pom.xml 형태는 http://araikuma.tistory.com/448 이분의 블로그를 참조해보자. 정말 친절하시다.
그외에 필요한 repo들은 https://mvnrepository.com/ 에서 확인할 수 있다.
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hbase/hbase-common -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-common</artifactId>
<version>2.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hbase/hbase-client -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.6</version>
</dependency>
</dependencies>그리고 추가로 아래와 같은 코드를 추가한다. 안하면 manifest가 없다는 에러를 발생하고, 또 with-dependencies를 이용해서 종속성을 포함한 jar파일이 생성된다. (처음에 이래서 compile때에는 lib를 찾다가 실행하니깐 못찾아서 한참 에러를 구경했다.....)
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>PutExample</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>책에 있는 내용과 동일하게 코드를 작성해주고 예제는 깃헙에 있다.☞ https://github.com/larsgeorge/hbase-book
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
public class PutExample {
public static void main(String[] args) throws IOException {
Configuration conf=HBaseConfiguration.create();
HTable table = new HTable(conf,"testtable");
Put put = new Put(Bytes.toBytes("row1"));
put.add(Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"), Bytes.toBytes("val1"));
put.add(Bytes.toBytes("colfam1"), Bytes.toBytes("qual2"), Bytes.toBytes("val2"));
table.put(put);
}
}이대로 하면 에러난다. 책은 0.9 버전이고 나는 2.1버전을 다운 받았기 때문ㅇ ㅔ,,, (눈물)
여러군데를 뒤져보아서 새로 코드를 작성했다. 그중에서 단연 도움이 된건 JAVA API example사이트와 HBASE API사이트.https://hbase.apache.org/2.0/apidocs/index.html
https://cloud.google.com/bigtable/docs/samples-java-hello
https://intellipaat.com/tutorial/hbase-tutorial/operations-using-java-api/
그래서 아래와 같이 코드를 재구성 했다. 변경된 것이 많은데 , 우선 HTable은 없어졌으니 Table을 쓰라고 한다.
.
그리고 Admin을 생성하고 table에 대한 descriptor를 생성하고 family 생성후 table을 생성해주면 된다.
//connection
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.Admin;import java.io.IOException; * 요것두 추가
//table create
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.HColumnDescriptor;
public class PutExample{
public static void main(String[] args) throws IOException {
HBaseConfiguration conf =new HBaseConfiguration(new Configuration());
Connection connection = ConnectionFactory.createConnection(conf);
Admin admin = connection.getAdmin();
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("testtable"));
tableDescriptor.addFamily(new HColumnDescriptor("colfam1")); //적어도 하나의 family는 명시해줘야한다고 한다. 오류뜸
admin.createTable(tableDescriptor);
System.out.println("create table testTable.."+tableDescriptor.getNameAsString());
table.close();connection.close();
}
}그리고서 shell에 접속하면 table list에 내가 생성한 테이블이 보인다.
위에 보면 Configuration이라는 객체를 맨 처음 생성하는 것을 볼 수 있다. 이는 코드상에서 클러스터의 위치를 알기 위해서 작성된 것이다.
클러스터의 위치를 알고자 할때는 hbase-site.xml에 접근하거나 코드에 명시해야하는데,이때 코드상에서 조작하려고 사용하는것이 Configuration이다.
그래서 이 configuration객체를 이용해서 hbase-site.xml 파일을 수정할 수 도 있다고 한다.
이렇게 하면, 클라이언트 측에서 외부 파일을 직접 참조해야하는 수고를 덜어줄 수 있다는 장점이 있다.
이제 Put 객체를 사용해보자. 아래쪽에 코드를 더 추가해주자. API를 보면 아래와 같이 되어있다. Connection을 이용해서 얻으세요~
//insert data
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.util.Bytes;
<.위에 코드들.....>Table table = connection.getTable(TableName.valueOf("testtable"));
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),Bytes.toBytes("val2"));
table.put(put);다시 hbase shell에서 scan을 해보면 내가 put으로 넣은 데이터가 잘 보인다 (*코드를 두번실행할땐 테이블이 이미존재한다는 에러가 뜨니 주의)
HBase의 특별한 기능 중 하나는 각 Cell에 여러 개의 버전을 저장할 수 있다는 것이다.
버전이라는 것은 위 그림과 같이 밀리초로 환산된 long integer 값인 timestamp를 이용하여 구현된다.
put을 이용할때 ts라는 파라미터를 명시하면 timestamp를 직접 지정할 수 있으며 그렇지 않으면 리전 서버에서 자동으로 설정해준다. 유닉스 시간이 default
.
사진 출처 : https://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%89%EC%8A%A4_%EC%8B%9C%EA%B0%84
아래 예시를 보면 VERSIONS => 3을 한경우에 3개까지 버전이 나왔다 (크거나 작다가 아니라 명시를 뜻하는 것)
책에 있는데로 그냥 create 'test'하면 versions를 3으로 해도 1개만 나오고 안된다.
기본적으로 versions가 1로 생성되어서 그러는 것 같다. 그래서 versions를 3으로 명시하여 테이블을 생성하니 아래와 같이 잘 나왔다.
그냥 scan을 하면 가장 최신 것을 보여준다.
참고 : https://stackoverflow.com/questions/26546743/hbase-table-is-not-showing-any-versioning
hbase(main):052:0> create 'test', {NAME => 'cf1', VERSIONS => 3}
Created table test
Took 1.2488 seconds
=> Hbase::Table - test
hbase(main):053:0> put 'test', 'row1','cf1','val1'
Took 0.2747 seconds
hbase(main):054:0> put 'test', 'row1','cf1','val2'
Took 0.0184 seconds
hbase(main):055:0> put 'test', 'row1','cf1','val3'
Took 0.0101 seconds
hbase(main):056:0> scan 'test'
ROW COLUMN+CELL
row1 column=cf1:, timestamp=1533870527379, value=val3
1 row(s)
Took 0.1733 seconds
hbase(main):057:0> scan 'test',{VERSIONS =>3}
ROW COLUMN+CELL
row1 column=cf1:, timestamp=1533870527379, value=val3
row1 column=cf1:, timestamp=1533870525282, value=val2
row1 column=cf1:, timestamp=1533870521845, value=val1
1 row(s)
Took 0.0355 secondsKEY VALUE 클래스
keyvalue는 특성 cell 하나의 데이터 및 데이터 베이스 내에서의 좌표 정보(로우 키, 컬럼패밀리 이름, 컬럼 퀄리파이어,타임스탬프)를 담고 있다.
생성하는 방법은 너무~ 많다. https://hbase.apache.org/2.0/apidocs/index.html
이중에서 책에서 소개한 생성자는 아래와 같은 모양이다.
데이터 및 좌표 정보는 모두 자바의 byte[] 타입으로 저장된다.
위에 파라미터를 보면 offset과 length가 있다. 이는 필요한 추가 저장공간을 최소화하여서 꼭~ 필요한 공간만 사용하기 위함이다. 이렇게 공간 효율적이기때문에 연산을 빠르게 수행 할 수 있다.
get메서드를 이용하면 각각의 바이트 배열 및 offset과 length를 얻을 수 있다. 이 수준까지 이용할 상황은 거의 없다고한다.^-^;; 그러니 이런게 있다고만 알아두라고 한다.
다음과 같은 메서드도 있다. (8장 아키텍처에서 더 자세하게 설명될 것이다.)
여기서 간단히만 살펴보자면 Key와 Row의 차이는 Row는 말그대로 Row key를 말하는 것이고 Cell의 Byte타입으로 저장된 좌표정보라고 설명했던 개념이 Key다. (음,,,책에서는 딱 이렇게 작성되어있는데, keyvalue생성자의 첫번째 파라미터를 말하는 것인가,,?)
비교 연산자를 제공해주고 있다. 문서에도 나와있지만 일부 클래스들은 이제 사라진다...~* 바이바이
아래와 같은 filed를 이용하여 위 class에 접근할 수 있다. 그래서 새로 생성안하고 고냥 접근이 가능하다.
keyvale 생성할때 Type이라는게 있었다. Type에 대해 알아보자.
이 필드에 사용 가능한 값은 다음과 같다. 책에서는 Put과 Delete<..>만 소개하고 있다.
Put : 해당 keyvale 인스턴스가 일반적인 Put 연산임을 의미함
Delete : 해당 keyvale 인스턴스가 Delete 연산임을 의미함 일명 툼스톤 마커(tombstone marker)라고도 한다.
DeleteColumn : Delete보다 더 광범위하게 전체 칼럼 삭제
DeleteFamily : Delete 보다 더 광범위하게 전체 칼럼 삭제 및 칼럼 패밀리까지 모두 삭제
toString()이라는 메서드를 사용하면 Keyvalue의 위의 어떤 유형인지를 <row-key>/<family>:<qualifier>/<version><type>/<value-length> 로 출력해준다.
클라이언트 측 쓰기 버퍼
HBASE API는 클라이언트 측 쓰기 버퍼를 내장하여 제공한다.
이 쓰기 버퍼는 쓰기 연산을 수집하여 한 번의 PRC로 서버에 전달한다. 이는 아래 그림과 같이 client와 server간에 요청을 주고받을때 요청을 주는시간과 그에 대한 응답을 하는데에 걸리는 시간인 round-trip time을 줄이기 위해 한번에 buffer에 연산을 담았다가 한번에 보내서 처리하는것을 이야기한다.
RPC는 https://ko.wikipedia.org/wiki/%EC%9B%90%EA%B2%A9_%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80_%ED%98%B8%EC%B6%9C 에 나와있다.
작년에 xml-rpc도 공부한 적 있다. http://weejw.tistory.com/81?category=776732
버퍼를 활성화 시키려면 메서드를 사용하면 된다(어디 클래스에 있는 메서드인지도 안알려준다 ㅡㅡ 하..)
void setAutoFlush(boolean autoFlush)
boolean isAutoFlush()
이 두가지 메서드는 HTable class에 있었다. 지금은 BufferedMutator 를 사용하여 버퍼를 설정해줄 수 있다.
(참고 https://stackoverflow.com/questions/31356639/how-to-set-autoflush-false-in-hbase-table)
setAuto,isAuto는 아예 쓰지 않으며 아래와 같이 해당 테이블의 BufferedMutator 객체를 만들어서 사용해야한다.
Table t = connection.getTable(TableName.valueOf("foo"));
BufferedMutator t = connection.getBufferedMutator(TableName.valueOf("foo"));
t.mutate(p);책에 있는 예제를 살펴보자. 아니다. 어차피 안될테니 쳐다도 안보겠다. 순서만 따라서 API보고 코드를 또 수정해보자.
아래 disableWriteBufferPeriodicFlush를 이용하여 버퍼를 사용할지 말지 할 수 있다. 파라미터는 없다. 그냥 호출만으로 disable시킬 수 있는 것 같다.
148 default void disableWriteBufferPeriodicFlush() { 149 setWriteBufferPeriodicFlush(0, MIN_WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS); 150 }
그에 반해 다음과 같이 주기를 설정할 수 있는 메서드도 있다.
그렇게 문서들을 참고해서 코드를 수정했다. 수정된건 사실 크게 없다. 앞에서 언급했던것들이 바뀐 것 뿐. flush 메서드가 HTable의 메서드였기때문에 이를 BufferedMutator Class의 메서드로 변경하였다.
BufferedMutator mutator = connection.getBufferedMutator(TableName.valueOf("testtable"));
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val1"));
mutator.mutate(put);
Put put2 = new Put(Bytes.toBytes("row2"));
put2.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val2"));
mutator.mutate(put2);
Put put3 = new Put(Bytes.toBytes("row3"));
put3.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val3"));
mutator.mutate(put3);
System.out.println("flush time : " + mutator.getWriteBufferPeriodicFlushTimerTickMs());
Get get = new Get(Bytes.toBytes("row1"));
Result res1 = table.get(get);
System.out.println("Result1 : "+res1);
mutator.flush();
Result res2 = table.get(get);
System.out.println("Result2 : "+res2);
mutator.close();
table.close();
connection.close();create table testTable..testtable
flush time : 1000
Result1 : keyvalues=NONE
Result2 : keyvalues={row1/colfam1:qual1/1533889064018/Put/vlen=4/seqid=0}처음 결과를 가져왔을때에는 NONE을 가져오고 있다. 이는 클라이언트 쓰기 버퍼가 메모리에 상주하는 구조로서 비워지지 않은 데이터를 그대로 들고 있기 때문이다. 아직 서버에 아무것도 전송되지 않았기 때문에 서버에서 접근할 수 없는 것이다.이렇게 하나하나 put 인스턴스를 mutate해줄 수도 있지만, list를 이용하여 한번에 처리할 수도 있다. 위에 코드에서 아래 부분만 수정해보자.import java.util.ArrayList;
import java.util.List;
< 중간 내용.. >
List<Mutation> mutations = new ArrayList<Mutation>();
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val1"));
mutations.add(put);
Put put2 = new Put(Bytes.toBytes("row2"));
put2.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val2"));
mutations.add(put2);
Put put3 = new Put(Bytes.toBytes("row3"));
put3.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val3"));
mutations.add(put3);
mutator.mutate(mutations);Result1 : keyvalues=NONE
Result2 : keyvalues={row1/colfam1:qual1/1533889915315/Put/vlen=4/seqid=0}강제로 에러를 발생시켜서 어떤 상황에서 에러가 발생하는지 알아보자.위에 코드에서 있지도 않음 컬럼 페밀리에다가 레코드를 삽입하려고 해보자. 당연히 없는 컬럼이라는 에러가 발생할 것이다.
Put put2 = new Put(Bytes.toBytes("row2"));
put2.addColumn(Bytes.toBytes("BOGUS"),Bytes.toBytes("qual1"),Bytes.toBytes("val2"));
mutations.add(put2);Exception in thread "main" org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException: Failed 1 action: org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException: Column family BOGUS does not exist in region testtable,,그렇다면 이 후에 넣었던 put3은 잘 들어갔을까? 아주 잘 들어가있다. 서버에서는 연산을 이터레이트하여 모두 실행하려고 하기때문이라고 한다.오류 메세지가 굉장히 긴데(그만큼 자세하게 알려준다) 그중에 보면 1time이라는 문구가 보인다. 이는 HBase가 바로잡을 수 없는 에러이기때문에 재시도 횟수가 자동으로 1로 설정된것이다.: 1 time, servers with issues: netdb.master.com,16020,1533790052263서버 측에서 실패한 Put 인스턴스들은 클라이언트의 쓰기 버퍼에 그대로 남게 되고 버퍼가 비워지는 다음 차례에 재시도 된다.에러를 하나 더 발생시켜보자. Put List를 하나 생성해서 내용이 없는 Put 인스턴스를 추가한다.List<Put> puts = new ArrayList<Put>();
Put put4 = new Put(Bytes.toBytes("row2"));
puts.add(put4);
try{
table.put(puts);
}catch (Exception e){
System.out.println("Error:"+e);
}Error:java.lang.IllegalArgumentException: No columns to insert리스트 기반 입력을 사용할 때는 서버 측에서 인력 연산이 적용되는 순서를 제어할 수 없다는 사실에 주의 해야한다.!원자적 '확인 후 입력' 연산입력 메서드에는 '확인 후 입력'이라는 고유 영역을 보장하는 특별한 종류가 있다. 이 메서드의 형태는 아래와 같다. 보면 알겠지만 Deprecated라고 또 있다.ㅎcheckandmutate를 사용하라고 한다.이 메서드는 특정 조건의 확인에 의해 감시되는 원자적인 서버 측 객체를 생성할 수 있게 해준다. (..?)조건의 확인이 성공하면 입력 연산이 실행되고 그렇지 않으면 연산은 버려진다. 이 메서드는 그래서 어떤 값의 현재 상태를 기반으로 데이터를 갱신하는 데 사용할 수 있다.(ex. 계좌 잔고, 상태 변환, 전산처리등을 수행하는 시스템)어느 시점에 한 지점에서 데이터를 읽어들인 후 특정한 처리를 수행한다.그리고 데이터를 읽어들인 곳에 그 결과를 적용할 준비가 되면, 혹시 동일한 작업을 다른 클라이언트에서 이미 해버리지는 않았는지 확인해야한다.원자적 확인을 사용하여 해당 값이 변경되지 않았음을 확인한 후 비로소 변경된 값을 적용한다.동기화 같은 개념인 것같다.이번엔 코드가 조금 길다. 코드를 찬찬히 살펴보자면첫번째,두번째 boolean : Put 객체를 생성하고 boolean 객체를 이용하여 컬럼이 존재하는지 확인하고 연산을 수행한다. res1은 처음에 컬럼이 존재하지 않았기때문에 값이 들어가지만 res2에서는 컬럼이 이미 존재하기때문에 false가 출력된다.세번째 boolean에서는 다른 컬럼 퀄리파이어를 사용하여 이전 데이터가 저장된 경우에만 새로운 데이터를 저장한다.네번째 boolean에서는 다른 로우를 사용하면서 새로운 데이터를 저장한다.Put put1 = new Put(Bytes.toBytes("row1"));
put1.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val1"));
boolean res1 = table.checkAndPut(Bytes.toBytes("row1"),
Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"), null, put1);
System.out.println("Put 1a applied: " + res1);
boolean res2 = table.checkAndPut(Bytes.toBytes("row1"),
Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"), null, put1);
System.out.println("Put 1b applied: " + res2);
Put put2 = new Put(Bytes.toBytes("row1"));
put2.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),Bytes.toBytes("val2"));
boolean res3 = table.checkAndPut(Bytes.toBytes("row1"),
Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"),Bytes.toBytes("val1"), put2);
System.out.println("Put 2 applied: " + res3);
Put put3 = new Put(Bytes.toBytes("row2"));
put3.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"),Bytes.toBytes("val3"));
boolean res4 = table.checkAndPut(Bytes.toBytes("row1"),
Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"),Bytes.toBytes("val1"), put3);
System.out.println("Put 3 applied: " + res4);Put 1a applied: true
Put 1b applied: false
Put 2 applied: true
Exception in thread "main" org.apache.hadoop.hbase.DoNotRetryIOException: org.apache.hadoop.hbase.DoNotRetryIOException: Action's getRow must match'2018년 > DataBase' 카테고리의 다른 글
3장 클라이언트 API : 기본기능 - Delete 메서드 (0) 2018.08.17 3장 클라이언트 API : 기본기능 - Get 메서드 (0) 2018.08.17 험난한 HBASE 설치기 (0) 2018.07.17 데이터마이닝 개념과 기법 개요 (2) 2018.03.15 “NoSQL부터 FaaS까지” 현대적인 데이터 아키텍처를 위한 7가지 핵심 기술"을 읽어보자 (0) 2018.02.27