Apache HBase 외부 API

Apache HBase 외부 API (Apache HBase External APIs)

네이티브 HBase API 외에 사용할 수 있는 외부 인터페이스(REST, Thrift, C/C++ 클라이언트, JDO, Scala, Jython)를 설명하는 페이지예요. REST는 URL 자체에 묶인 API로 테이블·행·셀·메타데이터를 리소스로 노출해요.

출처: 문서

본문

네이티브 HBase API 사용 방법은 User API Reference와 HBase APIs 챕터를 참고하세요.

REST

Representational State Transfer(REST)는 HTTP 사양의 주요 저자 중 한 명인 Roy Fielding의 박사 논문(2000)에서 소개됐어요.

REST 자체는 이 문서의 범위를 벗어나지만, 일반적으로 REST는 URL 자체에 묶인 API를 통해 클라이언트-서버 상호작용을 허용해요. 이 섹션은 HBase와 함께 제공되는 REST 서버를 구성·실행하는 방법을 논의해요. 이 서버는 HBase 테이블, 행, 셀, 메타데이터를 URL로 지정된 리소스로 노출해요. Jesse Anderson의 How-to: Use the Apache HBase REST Interface 시리즈 블로그도 좋아요.

REST 서버 시작·중지 (Starting and Stopping the REST Server)

포함된 REST 서버는 임베디드 Jetty 서블릿 컨테이너를 시작하고 그 안에 서블릿을 배포하는 데몬으로 실행할 수 있어요. 다음 명령 중 하나로 REST 서버를 포그라운드 또는 백그라운드로 시작하세요. 포트는 선택 사항이며 기본값은 8080이에요.

Foreground

$ bin/hbase rest start -p

Background, logging to a file in $HBASE_LOGS_DIR

$ bin/hbase-daemon.sh start rest -p

REST 서버를 중지하려면 포그라운드에서 실행 중이었다면 Ctrl-C를, 백그라운드에서 실행 중이었다면 다음 명령을 사용하세요.

$ bin/hbase-daemon.sh stop rest

REST 서버와 클라이언트 구성 (Configuring the REST Server and Client)

REST 서버와 클라이언트를 SSL로 구성하는 방법과 REST 서버의 doAs 가장(impersonation)에 대한 정보는 Configure the Thrift Gateway to Authenticate on Behalf of the Client와 Securing Apache HBase 챕터의 다른 부분을 참고하세요.

REST 엔드포인트 사용 (Using REST Endpoints)

다음 예제는 플레이스홀더 서버 http://example.com:8000을 사용하며, 아래 명령은 모두 curl이나 wget 명령으로 실행할 수 있어요. 헤더 없이 평문 텍스트(기본), "Accept: text/xml" 헤더로 XML, "Accept: application/json"으로 JSON, "Accept: application/x-protobuf"로 프로토콜 버퍼 출력을 요청할 수 있어요.

달리 명시되지 않으면 쿼리에는 GET, 생성·변형에는 PUT 또는 POST, 삭제에는 DELETE를 사용하세요.

클러스터 전역 엔드포인트 (Cluster-Wide Endpoints)

Endpoint HTTP Verb Description
/version/cluster GET 이 클러스터에서 실행 중인 HBase 버전
/version/rest GET HBase REST Server 버전
/status/cluster GET 클러스터 상태
/ GET 모든 비시스템 테이블 목록

예시:

Get cluster version

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/version/cluster"

Get REST server version

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/version/rest"

Get cluster status

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/status/cluster"

List all non-system tables

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/"

네임스페이스 엔드포인트 (Namespace Endpoints)

Endpoint HTTP Verb Description
/namespaces GET 모든 네임스페이스 나열
/namespaces/namespace GET 특정 네임스페이스 설명
/namespaces/namespace POST 새 네임스페이스 생성
/namespaces/namespace/tables GET 특정 네임스페이스의 모든 테이블 나열
/namespaces/namespace PUT 기존 네임스페이스 alter. 현재는 사용되지 않음
/namespaces/namespace DELETE 네임스페이스 삭제. 네임스페이스는 비어 있어야 함

예시:

List all namespaces

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/namespaces/"

Describe a specific namespace

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/namespaces/special_ns"

Create a new namespace

curl -vi -X POST
-H "Accept: text/xml"
"example.com:8000/namespaces/special_ns"

List all tables in a specific namespace

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/namespaces/special_ns/tables"

Alter an existing namespace

curl -vi -X PUT
-H "Accept: text/xml"
"http://example.com:8000/namespaces/special_ns

Delete a namespace

curl -vi -X DELETE
-H "Accept: text/xml"
"example.com:8000/namespaces/special_ns"

테이블 엔드포인트 (Table Endpoints)

Endpoint HTTP Verb Description
/table/exists GET 지정된 테이블이 존재하는지 반환
/table/schema GET 지정된 테이블의 스키마 설명
/table/schema POST 제공된 스키마 조각으로 기존 테이블 업데이트
/table/schema PUT 새 테이블 생성, 또는 기존 테이블 스키마 교체
/table/schema DELETE 테이블 삭제. /table/이 아닌 /table/schema 엔드포인트를 사용해야 함
/table/regions GET 테이블 region 나열

예시:

Check if table exists

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/exists"

Get table schema

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/schema"

Update table schema

curl -vi -X POST
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d ''
"http://example.com:8000/users/schema"

Create or replace table schema

curl -vi -X PUT
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d ''
"http://example.com:8000/users/schema"

Delete table

curl -vi -X DELETE
-H "Accept: text/xml"
"http://example.com:8000/users/schema"

List table regions

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/regions"

Get 연산 엔드포인트 (Endpoints for Get Operations)

Endpoint HTTP Verb Description
/table/row GET 단일 행의 모든 컬럼 가져오기. 값은 Base-64 인코딩됨. 여러 컬럼을 담을 수 있는 유형(xml, json, protobuf 등)의 "Accept" 요청 헤더 필요
/table/row/column:qualifier/timestamp GET 단일 컬럼 값 가져오기. 값은 Base-64 인코딩됨
/table/row/column:qualifier GET 단일 컬럼 값 가져오기. 값은 Base-64 인코딩됨
/table/row/column:qualifier?e=b64 GET URL-safe base64로 인코딩된 바이너리 rowkey·컬럼 이름으로 단일 컬럼 값 가져오기. 반환 값은 Base-64 인코딩됨
/table/row_prefix*/column GET 주어진 행 접두사와 컬럼 패밀리와 일치하는 행 조합 가져오기. 반환 값은 Base-64 인코딩됨
/table/row_prefix*/column:qualifier GET 주어진 행 접두사, 컬럼 패밀리, 퀄리파이어와 일치하는 행 조합 가져오기. 반환 값은 Base-64 인코딩됨
/table/multiget?row=row&row=row/column:qualifier&row=... GET 행/컬럼 조합 Multi-Get. 값은 Base-64 인코딩됨
/table/multiget?e=b64&row=row&row=row/column:qualifier&row=... GET URL-safe base64로 인코딩된 바이너리 rowkey·컬럼 이름으로 행/컬럼 조합 Multi-Get. 반환 값은 Base-64 인코딩됨
/table/multiget?row=row&row=row/column:qualifier&filter=url_encoded_filter GET 필터가 있는 행/컬럼 조합 Multi-Get. 필터는 Thrift Filter Language로 지정한 뒤 application/x-www-form-urlencoded MIME 형식 문자열로 인코딩. 이 예제는 PrefixFilter('row1') 사용
/table/multiget?row=row&row=row/column:qualifier&row=...&filter_b64=b64_encoded_filter GET 필터가 있는 행/컬럼 조합 Multi-Get. 필터는 Thrift Filter Language로 지정한 뒤 URL-safe base64로 인코딩. 이 예제는 PrefixFilter('row1') 사용
/table/row/column:qualifier/?v=number_of_versions GET 주어진 셀의 지정된 수의 버전 Multi-Get. 값은 Base-64 인코딩됨

예시:

Get all columns of a single row

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/row1"

Get single column with timestamp

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/row1/cf:a/1458586888395"

Get single column

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/row1/cf:a"

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/row1/cf:a/"

Get single column with base64 encoding

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/cm93MQ/Y2Y6YQ?e=b64"

curl -vi -X GET
-H "Accept: text/xml"
-H "Encoding: base64"
"http://example.com:8000/users/cm93MQ/Y2Y6YQ/"

Get rows with prefix

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/row*/cf"

Multi-get

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/multiget?row=row1&row=row2/cf:a"

Multi-get with base64

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/multiget?e=b64&row=cm93MQ&row=cm93Mg%2FY2Y6YQ"

Multi-get with filter

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/multiget?row=row1&row=row2/cf:a&filter=PrefixFilter%28%27row1%27%29"

Multi-get with base64 filter

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/multiget?row=row1&row=row2/cf:a&filter_b64=UHJlZml4RmlsdGVyKCdyb3cxJyk"

Get multiple versions

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/row1/cf:a?v=2"

Delete 연산 엔드포인트 (Endpoints for Delete Operations)

Endpoint HTTP Verb Description
/table/row DELETE 단일 행의 모든 컬럼 삭제
/table/row/column_family: DELETE 단일 행과 컬럼 패밀리의 모든 컬럼 삭제
/table/row/column:qualifier/timestamp DELETE 단일 컬럼 삭제
/table/row/column:qualifier DELETE 단일 컬럼 삭제
/table/row/column:qualifier?e=b64 DELETE URL-safe base64로 인코딩된 바이너리 rowkey·컬럼 이름으로 단일 컬럼 삭제

예시:

Delete all columns of a row

curl -vi -X DELETE
"http://example.com:8000/users/row1"

Delete all columns of a row and column family

curl -vi -X DELETE
"http://example.com:8000/users/row1/cf"

Delete a single column with timestamp

curl -vi -X DELETE
"http://example.com:8000/users/row1/cf:a/1458586888395"

Delete a single column

curl -vi -X DELETE
"http://example.com:8000/users/row1/cf:a"

curl -vi -X DELETE
-H "Accept: text/xml"
"http://example.com:8000/users/row1/cf:a/"

Delete with base64 encoding

curl -vi -X DELETE
"http://example.com:8000/users/cm93MQ/Y2Y6YQ?e=b64"

curl -vi -X DELETE
-H "Encoding: base64"
"http://example.com:8000/users/cm93MQ/Y2Y6YQ/"

스캔 연산의 상태 유지(stateful) 엔드포인트 (Stateful endpoints for Scan Operations)

Endpoint HTTP Verb Description
/table/scanner/ PUT Scanner 객체 가져오기. 다른 모든 Scan 연산에 필요. batch 매개변수를 스캔이 배치로 반환할 행 수로 조정
/table/scanner/ PUT Scanner 객체에 필터를 제공하거나 다른 방식으로 Scanner를 구성하려면 텍스트 파일을 만들고 필터를 추가
/table/scanner/scanner-id GET 스캐너에서 다음 배치 가져오기. 셀 값은 바이트 인코딩됨. 스캐너가 소진되면 HTTP 상태 204 반환
table/scanner/scanner-id DELETE 스캐너 삭제 및 사용 리소스 해제

필터 파일 예시는 다음을 포함해야 해요.

{ "type": "PrefixFilter", "value": "u123" }

예시:

Create a scanner

curl -vi -X PUT
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d ''
"http://example.com:8000/users/scanner/"

Create a scanner with filter from file

curl -vi -X PUT
-H "Accept: text/xml"
-H "Content-Type:text/xml"
-d @filter.txt
"http://example.com:8000/users/scanner/"

Get next batch from scanner

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/scanner/145869072824375522207"

Delete scanner

curl -vi -X DELETE
-H "Accept: text/xml"
"http://example.com:8000/users/scanner/145869072824375522207"

스캔 연산의 무상태(stateless) 엔드포인트 (Stateless endpoints for Scan Operations)

Endpoint HTTP Verb Description
/table/* GET 전체 테이블 스캔. 무상태 스캐너 엔드포인트는 결과를 반환하기 위해 후속 호출이 필요 없음
/table/*?limit=number_of_rows GET 테이블의 첫 번째 행 스캔
/table/*?column=column:qualifier GET 테이블의 주어진 컬럼 스캔
/table/*?column=column1:qualifier1,column2:qualifier2 GET 테이블의 둘 이상의 컬럼 스캔
/table/*?startrow=row&limit=number_of_rows GET 시작 행과 한도로 테이블 스캔
/table/row_prefix* GET 행 접두사로 테이블 스캔
/table/*?reversed=true GET 역순으로 테이블 스캔
/table/*?filter=url_encoded_filter GET PrefixFilter('row1') 필터로 스캔. 필터는 Thrift Filter Language로 지정한 뒤 application/x-www-form-urlencoded MIME 형식 문자열로 인코딩
/table/*?filter_b64=b64_encoded_filter GET PrefixFilter('row1') 필터로 스캔. 필터는 Thrift Filter Language로 지정한 뒤 URL-safe base64로 인코딩

예시:

Scan entire table

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*"

Scan with limit

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*?limit=1"

Scan single column

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*?column=cf:a"

Scan multiple columns

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*?column=cf:a,cf:b"

Scan with start row and limit

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*?startrow=row1&limit=2"

Scan with row prefix

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/row1*"

Scan in reverse

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*?reversed=true"

Scan with filter

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*?filter=PrefixFilter%28%27row1%27%29"

Scan with base64 filter

curl -vi -X GET
-H "Accept: text/xml"
"http://example.com:8000/users/*?filter_b64=UHJlZml4RmlsdGVyKCdyb3cxJyk"

stateful scanner API는 클라이언트가 스캔 도중 REST 서버 실패 시 스캔을 재시작할 것을 기대해요. 무상태(stateless)는 스캔 연산과 관련된 어떤 상태도 저장하지 않으며 모든 매개변수가 쿼리 매개변수로 지정돼요.

무상태 엔드포인트는 작은 결과에 최적화되어 있고, stateful scanner API는 큰 결과에도 사용할 수 있어요.

스캔 매개변수는 다음과 같아요.

  • startrow — 스캔의 시작 행.
  • endrow — 스캔의 끝 행.
  • column — 스캔할 컬럼의 쉼표 구분 목록.
  • starttime, endtime — 특정 버전 타임스탬프 범위 내의 컬럼만 검색하려면 시작·끝 시간을 모두 지정해야 함.
  • maxversions — 반환할 각 컬럼의 버전 수를 제한.
  • batchsize — 각 next() 호출에 대해 반환되는 최대 값 수를 제한.
  • limit — 스캔 연산에서 반환할 행 수.
  • cacheblocks — RegionServer에서 Block Cache를 사용할지 여부. 기본 true.
  • reversed — true로 설정하면 역방향 스캔이 실행. 기본 false.
  • filter — 스캔의 필터를 application/x-www-form-urlencoded MIME 형식 문자열로 지정할 수 있게 함.
  • filter_b64 — HBASE-28518 패치가 포함된 버전에서 filter_b64는 URL-safe base64 인코딩 필터를 지정할 수 있게 함. filter와 filter_b64를 모두 지정하면 filter_b64만 고려됨.
  • includeStartRow — 시작 행을 스캔에 포함할지 여부. 기본 true.
  • includeStopRow — 끝 행(중지 행)을 스캔에 포함할지 여부. 기본 false.

includeStartRow와 includeStopRow는 HBASE-28627을 포함한 버전에서만 지원돼요. 이 패치가 없는 버전은 이 매개변수를 무시하거나, 기본값이 아닌 값으로 설정하면 오류를 낼 거예요.

시작 행, 끝 행, limit 매개변수에 대해 더:

  • 시작 행, 끝 행, limit이 모두 지정되지 않으면 전체 테이블이 스캔됨.
  • 시작 행과 limit(예: N)이 지정되면 스캔 연산은 지정된 시작 행부터 N개의 행을 반환.
  • limit만 지정되면 스캔 연산은 테이블 시작부터 N개의 행을 반환.
  • limit과 끝 행이 지정되면 스캔 연산은 테이블 시작부터 끝 행까지 N개의 행을 반환. N행 전에 끝 행에 도달하면(예: M, M < N) M개의 행이 사용자에게 반환.
  • 시작 행, 끝 행, limit(예: N)이 모두 지정되고 N < 시작·끝 행 사이의 행 수이면 시작 행부터 N행이 사용자에게 반환. N > (시작·끝 행 사이의 행 수, 예: M)이면 M행이 사용자에게 반환.

Put 연산 엔드포인트 (Endpoints for Put Operations)

Endpoint HTTP Verb Description
/table/row_key PUT 테이블에 행 쓰기. 행, 컬럼 퀄리파이어, 값은 각각 Base-64 인코딩해야 함. 문자열 인코딩은 base64 커맨드라인 유틸리티 사용, 디코딩은 base64 -d. 페이로드는 --data 인자에 있고 /users/fakerow 값은 플레이스홀더. 여러 행은 요소에 추가해 삽입. 삽입할 데이터를 파일에 저장하고 -d @filename.txt 구문으로 -d 매개변수에 전달할 수도 있음

예시:

XML format

curl -vi -X PUT
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'dmFsdWU1Cg=='
"http://example.com:8000/users/fakerow"

JSON format

curl -vi -X PUT
-H "Accept: text/json"
-H "Content-Type: text/json"
-d '{"Row":[{"key":"cm93NQo=", "Cell": [{"column":"Y2Y6ZQo=", "$":"dmFsdWU1Cg=="}]}]}''
"example.com:8000/users/fakerow"

Check-And-Put 연산 엔드포인트 (Endpoints for Check-And-Put Operations)

Endpoint HTTP Verb Description
/table/row_key/?check=put PUT 조건부 Put — 셀의 현재 버전 값 변경: 셀의 현재 또는 최신 버전 값(current-version-value)을 check-value와 비교하고, current-version-value == check-value이면 새 데이터(new-value)를 현재 또는 최신 버전으로 셀에 씀. 행, 컬럼 퀄리파이어, 값은 각각 Base-64 인코딩해야 함. check 셀 이름(컬럼 패밀리:컬럼 이름)과 값이 항상 끝에, 같은 행 키의 새 Put 셀 이름(컬럼 패밀리:컬럼 이름)과 값 바로 뒤에 위치. 페이로드는 --data 또는 -d 인자에 있음. 삽입할 데이터를 파일에 저장하고 -d @filename.txt 구문으로 전달 가능

예시:

XML format

curl -vi -X PUT
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'T2xkR3V5TmV3R3V5'
"http://example.com:8000/users/row1/?check=put"

JSON format

curl -vi -X PUT
-H "Accept: application/json"
-H "Content-Type: application/json"
-d '{"Row":[{"key":"cm93MQ==","Cell":[{"column":"Y2ZhOmFsaWFz","$":"T2xkR3V5"},{"column":"Y2ZhOmFsaWFz", "$":"TmV3R3V5"}] }]}'
"http://example.com:8000/users/row1/?check=put"

상세 설명:

  • 위 json-format 예제에서:
    • -d 옵션 끝의 {"column":"Y2ZhOmFsaWFz", "$":"TmV3R3V5"}는 각각 Base-64의 check 셀 이름과 check 셀 값: "Y2ZhOmFsaWFz"는 "cfa:alias", "TmV3R3V5"는 "NewGuy".
    • {"column":"Y2ZhOmFsaWFz","$":"T2xkR3V5"}는 각각 Base-64의 새 Put 셀 이름과 셀 값: "Y2ZhOmFsaWFz"는 "cfa:alias", "T2xkR3V5"는 "OldGuy".
    • "cm93MQ=="는 checkAndPut row key용 "row1"의 Base-64.
    • 요청 URL의 row key 뒤의 "/?check=put"은 checkAndPut WebHBase 연산이 동작하는 데 필요.
    • 요청 URL의 "row key"는 URL-encoded여야 함. 예: "david%20chen"과 "row1"은 각각 행 키 "david chen"과 "row1"의 URL-encoded 형식.
    • 메모: "cfa"는 컬럼 패밀리 이름이고 "alias"는 non-Base64 인코딩 셀 이름의 컬럼(퀄리파이어) 이름.
  • 기본적으로 xml-format 예제는 json-format 예제와 같으며 여기서 자세히 설명하지 않겠음.

Check-And-Delete 연산 엔드포인트 (Endpoints for Check-And-Delete Operations)

Endpoint HTTP Verb Description
/table/row_key/?check=delete DELETE 조건부 행 삭제: 셀의 임의 버전 값(any-version-value)을 check-value와 비교하고, any-version-value == check-value이면 요청 URL 안의 row_key가 지정한 행을 삭제. 페이로드의 행, 컬럼 퀄리파이어, 값은 각각 Base-64 인코딩해야 함.
/table/row_key/column_family/?check=delete DELETE 조건부 행의 컬럼 패밀리 삭제: any-version-value를 check-value와 비교하고 같으면 요청 URL 안의 row_key/column_family가 지정한 행의 컬럼 패밀리 삭제. 나머지는 조건부 행 삭제와 동일
/table/row_key/column:qualifier/?check=delete DELETE 조건부 행의 컬럼 모든 버전 삭제: any-version-value를 check-value와 비교하고 같으면 요청 URL 안의 row_key/column:qualifier가 지정한 행의 컬럼 삭제. 요청 URL의 column:qualifier는 column_family:column_name
/table/row_key/column:qualifier/version_id/?check=delete DELETE 조건부 행의 컬럼 단일 버전 삭제: any-version-value를 check-value와 비교하고 같으면 요청 URL 안의 row_key/column:qualifier/version_id가 지정한 행의 컬럼 버전 삭제

예시:

Conditional delete a row (XML)

curl -vi -X DELETE
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'TmV3R3V5'
"http://example.com:8000/users/row1/?check=delete"

Conditional delete a row (JSON)

curl -vi -X DELETE
-H "Accept: application/json"
-H "Content-Type: application/json"
-d '{"Row":[{"key":"cm93MQ==","Cell":[{"column":"Y2ZhOmFsaWFz","$":"TmV3R3V5"}]}]}'
"http://example.com:8000/users/row1/?check=delete"

Conditional delete a column family (XML)

curl -vi -X DELETE
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'TmV3R3V5'
"http://example.com:8000/users/row1/cfa/?check=delete"

Conditional delete a column family (JSON)

curl -vi -X DELETE
-H "Accept: application/json"
-H "Content-Type: application/json"
-d '{"Row":[{"key":"cm93MQ==","Cell":[{"column":"Y2ZhOmFsaWFz","$":"TmV3R3V5"}]}]}'
"http://example.com:8000/users/row1/cfa/?check=delete"

Conditional delete all versions of a column (XML)

curl -vi -X DELETE
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'TmV3R3V5'
"http://example.com:8000/users/row1/cfa:alias/?check=delete"

Conditional delete all versions of a column (JSON)

curl -vi -X DELETE
-H "Accept: application/json"
-H "Content-Type: application/json"
-d '{"Row":[{"key":"cm93MQ==","Cell":[{"column":"Y2ZhOmFsaWFz","$":"TmV3R3V5"}]}]}'
"http://example.com:8000/users/row1/cfa:alias/?check=delete"

Conditional delete a single version (XML)

curl -vi -X DELETE
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'TmV3R3V5'
"http://example.com:8000/users/row1/cfa:alias/1519423552160/?check=delete"

Conditional delete a single version (JSON)

curl -vi -X DELETE
-H "Accept: application/json"
-H "Content-Type: application/json"
-d '{"Row":[{"key":"cm93MQ==","Cell":[{"column":"Y2ZhOmFsaWFz","$":"TmV3R3V5"}]}]}'
"http://example.com:8000/users/row1/cfa:alias/1519423552160/?check=delete"

상세 설명:

  • 위 4개의 json-format 예제에서:
    • -d 옵션 끝의 {"column":"Y2ZhOmFsaWFz", "$":"TmV3R3V5"}는 각각 Base-64의 check 셀 이름과 check 셀 값: "Y2ZhOmFsaWFz"는 "cfa:alias", "TmV3R3V5"는 "NewGuy".
    • "cm93MQ=="는 checkAndDelete row key용 "row1"의 Base-64.
    • 요청 URL 끝의 "/?check=delete"는 checkAndDelete WebHBase 연산이 동작하는 데 필요.
    • 마지막 json-format 예제의 요청 URL의 "version_id"는 "타임스탬프 번호 + 1"의 값과 같아야 함.
    • checkAndDelete WebHBase 연산의 요청 URL에 있는 "row key", "column family", "cell name" 또는 "column family:column name", "version_id"는 URL-encoded여야 함. 예제의 "row1", "cfa", "cfa:alias", "1519423552160"은 각각 URL-encoded된 "row key", "column family", "column family:column name", "version_id".
  • 기본적으로 4개의 xml-format 예제는 해당하는 4개의 json-format 예제와 같으며 여기서 자세히 설명하지 않겠음.

Append 연산 엔드포인트 (Endpoints for Append Operations)

Endpoint HTTP Verb Description
/table/row_key/?check=append PUT 주어진 새 값을 셀의 현재 값 끝에 추가. 행, 컬럼 퀄리파이어, 값은 각각 Base-64 인코딩해야 함

예시:

XML format

curl -vi -X PUT
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'dmFsdWU1Cg=='
"http://example.com:8000/users/row5?check=append"

JSON format

curl -vi -X PUT
-H "Content-type: application/json"
-H "Accept: application/json"
-d '{"Row":[{"key":"dGVzdHJvdzE=","Cell":[{"column":"YTox","$":"dGVzdHZhbHVlMgo"},{"column":"YToy","$":"dGVzdHZhbHVlMTIK"}]}]}'
"http://localhost:8080/users/testrow1?check=append"

Increment 연산 엔드포인트 (Endpoints for Increment Operations)

Endpoint HTTP Verb Description
/table/row_key/?check=increment PUT 셀의 현재 값 증가. 행, 컬럼 퀄리파이어, 값은 각각 Base-64 인코딩해야 함

예시:

XML format

curl -vi -X PUT
-H "Accept: text/xml"
-H "Content-Type: text/xml"
-d 'MQ=='
"http://localhost:8080/users/row5?check=increment"

JSON format

curl -vi -X PUT
-H "Content-type: application/json"
-H "Accept: application/json"
-d '{"Row":[{"key":"dGVzdHJvdzE=","Cell":[{"column":"YTox","$":"MQ=="},{"column":"YToy","$":"MQ=="}]}]}'
"http://localhost:8080/users/testrow1?check=increment"

REST XML 스키마 (REST XML Schema)

REST Protobufs 스키마 (REST Protobufs Schema)

message Version { optional string restVersion = 1; optional string jvmVersion = 2; optional string osVersion = 3; optional string serverVersion = 4; optional string jerseyVersion = 5; optional string version = 6; optional string revision = 7; }

message StorageClusterStatus { message Region { required bytes name = 1; optional int32 stores = 2; optional int32 storefiles = 3; optional int32 storefileSizeMB = 4; optional int32 memStoreSizeMB = 5; optional int64 storefileIndexSizeKB = 6; optional int64 readRequestsCount = 7; optional int64 writeRequestsCount = 8; optional int32 rootIndexSizeKB = 9; optional int32 totalStaticIndexSizeKB = 10; optional int32 totalStaticBloomSizeKB = 11; optional int64 totalCompactingKVs = 12; optional int64 currentCompactedKVs = 13; optional int64 cpRequestsCount = 14; } message Node { required string name = 1; // name:port optional int64 startCode = 2; optional int32 requests = 3; optional int32 heapSizeMB = 4; optional int32 maxHeapSizeMB = 5; repeated Region regions = 6; } // node status repeated Node liveNodes = 1; repeated string deadNodes = 2; // summary statistics optional int32 regions = 3; optional int32 requests = 4; optional double averageLoad = 5; }

message TableList { repeated string name = 1; }

message TableInfo { required string name = 1; message Region { required string name = 1; optional bytes startKey = 2; optional bytes endKey = 3; optional int64 id = 4; optional string location = 5; } repeated Region regions = 2; }

message TableSchema { optional string name = 1; message Attribute { required string name = 1; required string value = 2; } repeated Attribute attrs = 2; repeated ColumnSchema columns = 3; // optional helpful encodings of commonly used attributes optional bool inMemory = 4; optional bool readOnly = 5; }

message ColumnSchema { optional string name = 1; message Attribute { required string name = 1; required string value = 2; } repeated Attribute attrs = 2; // optional helpful encodings of commonly used attributes optional int32 ttl = 3; optional int32 maxVersions = 4; optional string compression = 5; }

message Cell { optional bytes row = 1; // unused if Cell is in a CellSet optional bytes column = 2; optional int64 timestamp = 3; optional bytes data = 4; }

message CellSet { message Row { required bytes key = 1; repeated Cell values = 2; } repeated Row rows = 1; }

message Scanner { optional bytes startRow = 1; optional bytes endRow = 2; repeated bytes columns = 3; optional int32 batch = 4; optional int64 startTime = 5; optional int64 endTime = 6; optional int32 maxVersions = 7; optional string filter = 8; optional int32 caching = 9; // specifies REST scanner caching repeated string labels = 10; optional bool cacheBlocks = 11; // server side block caching hint optional int32 limit = 12; optional bool includeStartRow = 13; optional bool includeStopRow = 14; }

Thrift

Thrift에 대한 문서는 Thrift API and Filter Language로 이동했어요.

C/C++ Apache HBase 클라이언트 (C/C++ Apache HBase Client)

FB의 Chip Turner가 순수 C/C++ 클라이언트를 작성했어요. 확인해 보세요.

C++ 클라이언트 구현. HBASE-14850을 참고하세요.

HBase에서 Java Data Objects (JDO) 사용 (Using Java Data Objects (JDO) with HBase)

Java Data Objects (JDO)는 일반 Java 객체(POJO)로 영구 데이터를 나타내 데이터베이스의 영구 데이터에 접근하는 표준 방식이에요.

의존성 (Dependencies)

이 코드 예제의 의존성:

  1. HBase 0.90.x 또는 더 새로운 버전
  2. commons-beanutils.jar (https://commons.apache.org/)
  3. commons-pool-1.5.5.jar (https://commons.apache.org/)
  4. HBase 0.90용 transactional-tableindexed (https://github.com/hbase-trx/hbase-transactional-tableindexed)

hbase-jdo 다운로드 (Download hbase-jdo)

코드를 http://code.google.com/p/hbase-jdo/에서 다운로드하세요.

JDO 예제 (JDO Example)

이 예제는 JDO로 테이블과 인덱스를 만들고, 테이블에 행을 삽입하고, 행을 가져오고, 컬럼 값을 가져오고, 쿼리를 수행하며, 몇 가지 추가 HBase 연산을 수행해요.

package com.apache.hadoop.hbase.client.jdo.examples;

import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.Hashtable;

import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.client.tableindexed.IndexedTable;

import com.apache.hadoop.hbase.client.jdo.AbstractHBaseDBO; import com.apache.hadoop.hbase.client.jdo.HBaseBigFile; import com.apache.hadoop.hbase.client.jdo.HBaseDBOImpl; import com.apache.hadoop.hbase.client.jdo.query.DeleteQuery; import com.apache.hadoop.hbase.client.jdo.query.HBaseOrder; import com.apache.hadoop.hbase.client.jdo.query.HBaseParam; import com.apache.hadoop.hbase.client.jdo.query.InsertQuery; import com.apache.hadoop.hbase.client.jdo.query.QSearch; import com.apache.hadoop.hbase.client.jdo.query.SelectQuery; import com.apache.hadoop.hbase.client.jdo.query.UpdateQuery;

/**

  • Hbase JDO Example.
  • dependency library.
    • commons-beanutils.jar
    • commons-pool-1.5.5.jar
    • hbase0.90.0-transactionl.jar
  • you can expand Delete,Select,Update,Insert Query classes.

*/ public class HBaseExample { public static void main(String[] args) throws Exception { AbstractHBaseDBO dbo = new HBaseDBOImpl();

//*drop if table is already exist.*
if(dbo.isTableExist("user")){
 dbo.deleteTable("user");
}

//*create table*
dbo.createTableIfNotExist("user",HBaseOrder.DESC,"account");
//dbo.createTableIfNotExist("user",HBaseOrder.ASC,"account");

//create index.
String[] cols={"id","name"};
dbo.addIndexExistingTable("user","account",cols);

//insert
InsertQuery insert = dbo.createInsertQuery("user");
UserBean bean = new UserBean();
bean.setFamily("account");
bean.setAge(20);
bean.setEmail("[email protected]");
bean.setId("ncanis");
bean.setName("ncanis");
bean.setPassword("1111");
insert.insert(bean);

//select 1 row
SelectQuery select = dbo.createSelectQuery("user");
UserBean resultBean = (UserBean)select.select(bean.getRow(),UserBean.class);

// select column value.
String value = (String)select.selectColumn(bean.getRow(),"account","id",String.class);

// search with option (QSearch has EQUAL, NOT_EQUAL, LIKE)
// select id,password,name,email from account where id='ncanis' limit startRow,20
HBaseParam param = new HBaseParam();
param.setPage(bean.getRow(),20);
param.addColumn("id","password","name","email");
param.addSearchOption("id","ncanis",QSearch.EQUAL);
select.search("account", param, UserBean.class);

// search column value is existing.
boolean isExist = select.existColumnValue("account","id","ncanis".getBytes());

// update password.
UpdateQuery update = dbo.createUpdateQuery("user");
Hashtable<String, byte[]> colsTable = new Hashtable<String, byte[]>();
colsTable.put("password","2222".getBytes());
update.update(bean.getRow(),"account",colsTable);

//delete
DeleteQuery delete = dbo.createDeleteQuery("user");
delete.deleteRow(resultBean.getRow());

////////////////////////////////////
// etc

// HTable pool with apache commons pool
// borrow and release. HBasePoolManager(maxActive, minIdle etc..)
IndexedTable table = dbo.getPool().borrow("user");
dbo.getPool().release(table);

// upload bigFile by hadoop directly.
HBaseBigFile bigFile = new HBaseBigFile();
File file = new File("doc/movie.avi");
FileInputStream fis = new FileInputStream(file);
Path rootPath = new Path("/files/");
String filename = "movie.avi";
bigFile.uploadFile(rootPath,filename,fis,true);

// receive file stream from hadoop.
Path p = new Path(rootPath,filename);
InputStream is = bigFile.path2Stream(p,4096);

} }

Scala

클래스패스 설정 (Setting the Classpath)

HBase와 함께 Scala를 사용하려면 CLASSPATH에 HBase 클래스패스와 코드에 필요한 Scala JAR이 포함되어야 해요. 먼저 HBase RegionServer 프로세스가 실행 중인 서버에서 다음 명령을 사용해 HBase 클래스패스를 얻으세요.

$ ps aux |grep regionserver| awk -F 'java.library.path=' {'print $2'} | awk {'print $1'} /usr/lib/hadoop/lib/native:/usr/lib/hbase/lib/native/Linux-amd64-64

$CLASSPATH 환경 변수를 이전 단계에서 찾은 경로와 scala-library.jar의 경로 및 프로젝트에 필요한 각 추가 Scala 관련 JAR을 포함하도록 설정하세요.

$ export CLASSPATH=$CLASSPATH:/usr/lib/hadoop/lib/native:/usr/lib/hbase/lib/native/Linux-amd64-64:/path/to/scala-library.jar

Scala SBT 파일 (Scala SBT File)

build.sbt 파일은 HBase와 함께 동작하려면 다음 resolvers와 libraryDependencies가 필요해요.

resolvers += "Apache HBase" at "https://repository.apache.org/content/repositories/releases"

resolvers += "Thrift" at "https://people.apache.org/~rawson/repo/"

libraryDependencies ++= Seq( "org.apache.hadoop" % "hadoop-core" % "0.20.2", "org.apache.hbase" % "hbase" % "0.90.4" )

Scala 코드 예시 (Example Scala Code)

이 예제는 HBase 테이블을 나열하고, 새 테이블을 만들고, 행을 추가하고, 행의 값을 가져와요.

import org.apache.hadoop.hbase.{HBaseConfiguration, TableName} import org.apache.hadoop.hbase.client.{Admin, Connection, ConnectionFactory, Get, Put} import org.apache.hadoop.hbase.util.Bytes

val conf = HBaseConfiguration.create() val connection = ConnectionFactory.createConnection(conf); val admin = connection.getAdmin();

// list the tables val listtables = admin.listTables() listtables.foreach(println)

// let's insert some data in 'mytable' and get the row val table = connection.getTable(TableName.valueOf("mytable"))

val theput = new Put(Bytes.toBytes("rowkey1"))

theput.addColumn(Bytes.toBytes("ids"),Bytes.toBytes("id1"),Bytes.toBytes("one")) table.put(theput)

val theget = new Get(Bytes.toBytes("rowkey1")) val result = table.get(theget) val value = result.value() println(Bytes.toString(value))

Jython

클래스패스 설정 (Setting the Classpath)

HBase와 함께 Jython을 사용하려면 CLASSPATH에 HBase 클래스패스와 코드에 필요한 Jython JAR이 포함되어야 해요.

jython.jar와 프로젝트에 필요한 각 추가 Jython 관련 JAR이 있는 디렉터리 경로를 설정하세요. 그런 다음 $JYTHON_HOME env 변수를 가리키도록 HBASE_CLASSPATH를 export하세요.

$ export HBASE_CLASSPATH=/directory/jython.jar

클래스패스에 HBase와 Hadoop JAR이 있는 Jython 셸을 시작하세요:

$ bin/hbase org.python.util.jython

Jython 코드 예시 (Jython Code Examples)

예제: Jython으로 테이블 생성, 채우기, Get, Delete

다음 Jython 코드 예제는 테이블을 확인하고, 존재하면 삭제한 뒤 생성해요. 그런 다음 데이터로 테이블을 채우고 데이터를 가져와요.

import java.lang from org.apache.hadoop.hbase import HBaseConfiguration, HTableDescriptor, HColumnDescriptor, TableName from org.apache.hadoop.hbase.client import Admin, Connection, ConnectionFactory, Get, Put, Result, Table from org.apache.hadoop.conf import Configuration

First get a conf object. This will read in the configuration

that is out in your hbase-*.xml files such as location of the

hbase master node.

conf = HBaseConfiguration.create() connection = ConnectionFactory.createConnection(conf) admin = connection.getAdmin()

Create a table named 'test' that has a column family

named 'content'.

tableName = TableName.valueOf("test") table = connection.getTable(tableName)

desc = HTableDescriptor(tableName) desc.addFamily(HColumnDescriptor("content"))

Drop and recreate if it exists

if admin.tableExists(tableName): admin.disableTable(tableName) admin.deleteTable(tableName)

admin.createTable(desc)

Add content to 'column:' on a row named 'row_x'

row = 'row_x' put = Put(row) put.addColumn("content", "qual", "some content") table.put(put)

Now fetch the content just added, returns a byte[]

get = Get(row)

result = table.get(get) data = java.lang.String(result.getValue("content", "qual"), "UTF8")

print "The fetched row contains the value '%s'" % data

예제: Jython으로 테이블 스캔

이 예제는 테이블을 스캔하고 주어진 패밀리 퀄리파이어와 일치하는 결과를 반환해요.

import java.lang from org.apache.hadoop.hbase import TableName, HBaseConfiguration from org.apache.hadoop.hbase.client import Connection, ConnectionFactory, Result, ResultScanner, Table, Admin from org.apache.hadoop.conf import Configuration conf = HBaseConfiguration.create() connection = ConnectionFactory.createConnection(conf) admin = connection.getAdmin() tableName = TableName.valueOf('wiki') table = connection.getTable(tableName)

cf = "title" attr = "attr" scanner = table.getScanner(cf) while 1: result = scanner.next() if not result: break print java.lang.String(result.row), java.lang.String(result.getValue(cf, attr))

더 알아보기 (Learn more)