
※ HBase란?
HBase는 HDFS 위에서 동작하는 Hadoop 생태계 기반의 분산 NoSQL 데이터베이스로,
초대규모 데이터를 RowKey 기반으로 빠르게 저장·조회하는 데 강점을 가진다.
- 수평 확장(Scale-out)에 매우 유리
- RowKey 기준 사전순 정렬 구조
- 컬럼 패밀리(Column Family) 기반 물리 저장
- 실시간 매트릭·로그 등 대량 쓰기 중심 데이터에 적합
- SQL이 아닌 put/get/scan/delete 기반 API 사용
HBase를 제대로 사용하려면 RowKey 설계와 scan 동작 방식을 이해하는 것이 핵심이다.
※ HBase 데이터 모델 구조
HBase는 RDBMS와 구조가 완전히 다르다.
| 요소 | 설명 |
| RowKey | 정렬 + 파티션 기준 (가장 중요) |
| Column Family (CF) | 논리적 컬럼 그룹 (생성 시 고정) |
| Qualifier | CF 아래 동적으로 생성되는 컬럼 |
| Timestamp | Cell 버전 (Update는 버전 추가) |
| Cell | RowKey + CF + Qualifier + Timestamp + Value |
즉, RowKey가 곧 데이터 정렬의 기준이며 HBase 성능의 핵심이다.
※ RowKey 설계 - 사실상 HBase의 모든 것
RowKey 설계는 HBase 성능과 조회 방식을 결정짓는다.
▶ Timestamp 기반 RowKey
YYYYMMDDHHmmss|instanceId # 20251216120000|redis01
epochMillis|instanceId # 1765854000000|redis01
reversedTimestamp|instance # 9223370271000775807|redis01
<장점>
RowKey의 앞부분에 시간 값이 위치하도록 설계되어 있어 데이터가 시간 순으로 정렬된다.
이로 인해 REVERSED 옵션을 사용하면 최신 데이터부터 조회할 수 있으며,
특정 시간 구간을 기준으로 한 범위 스캔도 효율적으로 수행할 수 있다.
▶ Prefix + Timestamp
Prefix|Timestamp|Identifier # redis01|20251216|used_memory
<장점>
특정 서버/인스턴스별 조회에 효과적
▶ Salting (Hotspot 방지)
salt|timestamp|instanceId # 03|20251216120000|redis01
# salt 값은 RowKey write hotspot 방지를 위해 사용하며, 실무에서 많이 사용하는 방식은 아래와 같다.
# salt = hash(timestamp) % N
# - 시간 증가로 인한 순차 write hotspot 방지에 효과적
# salt = hash(instanceId) % N
# - 인스턴스 단위 조회가 잦은 모니터링 환경에 적합
# salt = hash(timestamp + instanceId) % N
# - 시간, 인스턴스 트래픽 쏠림을 동시에 완화하는 방식
# N 값은 write 트래픽(QPS) 기준으로 선택
# 16(일반적인 모니터링/매트릭), 32(쓰기 트래픽이 높은 경우), 64(초고트래픽 로그 수집 환경)
<장점>
대량의 write(put)가 특정 Region으로 집중되는 Hotspot을 방지하여, 여러 Region으로 분산 처리하는 데 도움
※ HBase Shell 기본 명령어
▶ HBase 접속
hbase shell
▶ 테이블 목록
list
▶ 테이블 구조 확인
describe '테이블명'
▶ 데이터 샘플 조회
scan '테이블명', { LIMIT => 숫자 }
# 숫자는 Row 수가 아닌 RowKey 수
▶ 단일 Row 조회
get '테이블명', 'RowKey값'
※ scan (조회) 옵션 정리
▶ LIMIT - 조회할 RowKey 수 제한 (거의 필수)
scan '테이블명', { LIMIT => 숫자 }
▶ STARTROW / STOPROW - RowKey 범위 지정 조회
scan '테이블명', {
STARTROW => 'RowKey의 앞에서부터 일부',
STOPROW => 'RowKey의 앞에서부터 일부',
LIMIT => 숫자
}
▶ COLUMNS - 특정 컬럼명만 조회
scan '테이블명', {
COLUMNS => ['cf:컬럼명1', 'cf:컬럼명2', 'cf:컬럼명3'],
LIMIT => 숫자
}
scan '테이블명', {
COLUMNS => ['cf:컬럼명1'],
FILTER => "QualifierFilter(=, 'binary:컬럼명1')",
LIMIT => 숫자
}
# QualifierFilter와 함께 사용하면 네트워크/메모리 사용량 감소
▶ REVERSED - RowKey 역순 조회
scan '테이블명', { REVERSED => true, LIMIT => 숫자 }
# RowKey가 Timestamp 기반일 때(Timestamp가 RowKey 앞쪽에 설계된 경우)만 최신순처럼 보임
▶ FILTER - 조건 필터 조회
scan '테이블명', {
FILTER => "필터 표현식",
LIMIT => 숫자
}
RowKey 패턴 필터 조회
scan '테이블명', {
FILTER => "RowFilter(=, 'regexstring:.*202512.*')",
LIMIT => 숫자
}
# 202512는 조회할 RowKey 문자열 중 일부 (정규식 매칭)
컬럼명 필터 조회
scan '테이블명', {
FILTER => "QualifierFilter(=, 'binary:컬럼명1')",
LIMIT => 숫자
}
scan '테이블명', {
COLUMNS => ['cf:컬럼명1'],
FILTER => "QualifierFilter(=, 'binary:컬럼명1')",
LIMIT => 숫자
}
# COLUMNS와 함께 사용하면 네트워크/메모리 사용량 감소
특정 컬럼 값 조건 필터 조회
scan '테이블명', {
FILTER => "SingleColumnValueFilter('cf','컬럼명1', >, 'binary:컬럼값1')",
LIMIT => 숫자
}
# 컬럼명1의 값이 컬럼값1보다 큰 row만 조회
필터 조합 조회 (AND)
scan '테이블명', {
FILTER =>
"RowFilter(=,'regexstring:.*202512.*') AND
QualifierFilter(=,'binary:컬럼명1')",
LIMIT => 숫자
}
# 202512는 조회할 RowKey 문자열 중 일부 (정규식 매칭)
※ INSERT/UPDATE/DELETE
HBase는 RDBMS처럼 SQL을 사용하는 데이터베이스가 아니다.
따라서 INSERT/UPDATE/DELETE 문은 존재하지 않지만,이에 대응되는 동작은 put, delete 명령으로 수행한다.
▶ INSERT = put
put '테이블명', 'RowKey값', 'cf:컬럼명1', '컬럼값1'
▶ UPDATE = put
put '테이블명', 'RowKey값', 'cf:컬럼명1', '컬럼값1'
put '테이블명', 'RowKey값', 'cf:컬럼명1', '컬럼값2'
# 동일 RowKey + 동일 컬럼에 대해 put을 여러 번 수행하면
# 새로운 버전이 추가되며, 최신 값만 기본 조회 대상이 됨
▶ DELETE = delete/deleteall
delete '테이블명', 'RowKey값', 'cf:컬럼명1'
deleteall '테이블명', 'RowKey값'
# delete는 즉시 물리 삭제가 아니라 tombstone(삭제 마커)를 남김
# 실제 데이터 제거는 compaction(HBase가 내부적으로 수행하는 정리 작업) 과정에서 수행됨