[HBase] HBase Row Key Design

Hyunjun Kim·2025년 9월 1일
0

Data_Engineering

목록 보기
149/153

4 HBase Row Key Design

HBase는 Row Key라는 단일 인덱스로 데이터를 검색한다.
데이터의 위치와 분산은 Row Key에 의해 결정되므로, Row Key는 검색 성능뿐만 아니라 클러스터의 전체 상태에도 직접적인 영향을 미친다.
따라서 Row Key는 활용 목적에 맞게 신중하게 정의해야 하며, 클러스터에 부정적인 영향을 줄 수 있는 설계 방식은 피해야 한다.

4.1 Hotspotting

HBase의 Row Key는 사전순(lexicographical)으로 정렬된다.
이 덕분에 특정 범위의 데이터를 빠르게 검색하거나, 관련된 row들을 물리적으로 가까운 위치에 저장할 수 있다.
하지만 이 특성이 Row Key를 잘못 설계했을 때 성능 병목(Hotspotting)으로 이어질 수 있다.

4.1.1 Hotspot이란?

Hotspot은 다수의 클라이언트 요청이 특정 RegionServer에 집중되는 현상이다.

  • 클라이언트 트래픽이 클러스터의 한 노드 또는 몇 개의 노드에만 연결되어 부하가 특정 노드로 쏠리는 것을 말한다. 이 트래픽은 읽기, 쓰기 또는 기타 작업 모두 포함한다.
  • 쓰기 시 핫스팟을 방지하려면 Row Key를 설계할 때 특정 구간의 Row가 한 리전에만 집중되지 않도록 해야 한다.
    • 즉, 관련성이 있는 데이터는 논리적으로 인접하게 두되, 더 큰 관점에서는 데이터가 클러스터의 여러 리전에 고르게 분산되어 기록되도록 설계해야 한다.
  • Row Key 설계의 첫 번째 원칙은 핫스팟을 방지하는 것이다.
    • 그 다음으로는 Row Key가 사전순(lexicographical)으로 정렬되는 특성을 고려하여, Scan 연산의 효율성을 높이는 것이 중요하다.

Hotspot 발생 시:

  • 해당 RegionServer의 부하 급증 → 응답 지연
  • 같은 서버에 있는 다른 Region까지 영향
  • 심한 경우 Region이 일시적으로 사용 불가 상태

    즉, 클러스터 전체 자원이 고르게 활용되지 못하고 일부 노드만 과부하 상태에 빠진다.
    클러스터를 완벽하고 고르게 활용할 수 있도록 데이터 액세스 패턴을 설계하는 것이 중요하다.

Hotspot의 원인 : 잘못된 Row Key 설계

예를 들어:

  • user_00000001, user_00000002, … 처럼 순차 증가 값을 Row Key 앞부분에 두면
    → 새로운 데이터가 항상 같은 Region에 몰린다.
  • 로그 테이블에서 2025-09-01-00:00:00 같은 시간 기반 prefix를 쓰면
    → 특정 시간대 기록이 특정 Region에 집중된다.

즉, Row Key의 “앞부분”이 비슷하거나 동일하게 몰리면 Hotspot이 발생한다.

해결 원칙

  1. Row Key 분산 설계

    • Row Key를 단순히 순차적 증가값으로 만들지 않는다.
    • prefix를 해싱하거나 랜덤 요소(salt)를 추가해서 여러 Region에 분산되도록 한다.
  2. 논리적 인접성과 물리적 분산의 균형

    • 관련성이 높은 데이터는 같은 Row Key 범위에 두어 스캔 효율을 유지하되,
    • 전체적으로는 데이터가 클러스터에 고르게 분산되도록 설계한다.

4.1.2 Hotspot 방지 기법

Salting

Salting 은 주로 암호화 할 때 사용되는 용어/기법이다. 랜덤한 숫자나 문자를 붙이는 것을 말한다.
원래 사용하려고 했던 rowkey 앞에 정해진 문자 (e.g. 알파벳)을 랜덤하게 붙이는 방식이다.
이 방법은 통해 데이터가 random 하게 Region 에 고르게 퍼지는 것을 기대할 수 있다.

예 - original keys

foo0001
foo0002
foo0003
foo0004

예 - salting 적용

a-foo0003
b-foo0001
c-foo0003
c-foo0004
d-foo0002

Salting 방법은 write 에 대한 throughput 을 높일수는 있지만, read 에서는 여러 리전에 걸쳐 읽어야 하므로 성능이 떨어질 수 있다.
또한 random 하게 부여한 salt 값을 read 할 때 어떻게 알게 할 것인지는 추가로 고민이 필요하다.

Range scan 이 필요한 데이터에는 적합하지 않다. 단일 데이터를 위주로 조회 (예: user 정보와 같은 metadata 종류)하는 경우에 사용하는 것이 적합하다.


Hashing

Row key 에 들어갈 원래 값을 Hashing 한 값을 row key로 사용하는 방법이다.
주어진 Row가 항상 동일한 접두사로 "salt"되어 로드를 RegionServer에 분산시키고, 읽기를 예측 가능하다는 것이 장점이다.
결정론적 해시를 사용하면 클라이언트가 전체 Row Key를 재구성하고 Get 작업을 사용하여 해당 Row을 정상적으로 검색할 수 있다.

Hasing 은 또한 더 적은 수의 용량으로 더 많은 경우의 수를 표현할 수 있다는 장점도 있다.

  • SHA256 의 경우 256 bit 으로 2^256 경우의 수를 표현할 수 있다.

Reversing the Key

fixed-width row key 또는 numeric row key 를 least significant digit 을 앞에 두어 revesre 하는 것이다.

장점: 일부 분산 효과, 단순한 random 효과
단점: 숫자 기반 ordering 깨짐 → scan 연산 주의 필요



4.2 Monotonically Increasing Row Keys/Timeseries Data

단방향으로 증가하는 rowkey는 HBase Row Key의 Anti-Pattern 이다.
가장 대표적인 예로 timestamp 를 맨 앞에 위치시키는 방식이 있다.

4.2.1 왜 문제가 될까?

Facebook의 타임라인을 예로 들어보자.
사용자가 소비하는 콘텐츠는 대부분 최신 데이터이다.
즉, 지난 1시간, 지난 1일 등 최근 시점의 timestamp가 Row Key 맨 앞에 오면,
해당 시점에 해당하는 Row들이 특정 Region에 몰리게 된다.

결과적으로 읽기 요청이 모두 동일한 RegionServer에 집중되어 Hotspot이 발생한다

4.2.2 Domino Effect (최악의 시나리오)

  1. 특정 RegionServer가 부하를 감당하지 못함 → 응답 지연
  2. 최악의 경우, 해당 RegionServer 다운
  3. HBase는 자동 복구(fault tolerance) 기능으로 해당 Region을 다른 노드에 재할당
  4. 새로운 노드도 같은 과부하에 걸림
  5. 도미노처럼 차례차례 클러스터 전체가 불안정해질 수 있음

이는 HBase에서 발생할 수 있는 최악의 운영 시나리오다.

4.2.3 그러나 Timestamp는 여전히 필요하다

문제는, timestamp 기반 Row Key가 무조건 나쁘다는 것이 아니다.
Range Scan이 필요한 경우(예: 최신 데이터 순 조회) timestamp는 매우 유용하다.

  • 온라인 서비스 대부분은 최신 데이터를 우선 노출
  • 유저는 빠른 응답을 기대
  • 따라서 Row Key에 timestamp를 포함하는 것은 필요

4.2.4 해결 방법: Prefix + Timestamp

핵심은 Row Key의 앞부분에 분산 요소(prefix)를 넣는 것이다.

예시

user_id : timestamp : 기타정보
  • user_id가 랜덤하게 분포된 값이라면, 데이터는 여러 Region에 고르게 퍼짐
    • 같은 user_id 내에서는 timestamp 순서가 유지되므로 타임라인 조회도 가능
  • User 페이지: 해당 유저의 최신 데이터를 timestamp 순으로 바로 조회 가능
  • 전체 Timeline: 별도의 알고리즘/서비스 계층에서 정렬 처리


4.3 Try to minimize row and column sizes

HBase에서 Value는 단독으로 존재하지 않고, 항상 해당 Cell의 좌표 정보(coordinates = Row, Column name, Timestamp)와 함께 저장되고 전송된다.

coordinates = Row Key + Column Name + Timestamp

즉, Cell Value가 시스템을 통과할 때는 Value 자체뿐 아니라 좌표 정보(coordinates)가 반드시 포함된다.

  • 클라이언트 ↔ 서버 간 전송, HFile 저장, 인덱스 관리 등 모든 경로에서 Value + coordinates 조합이 반복적으로 사용된다.

4.3.1 왜 문제가 될까?

문제는 좌표 정보(coordinates)의 크기가 Value 크기와 비교해 상대적으로 클 경우 발생한다.

  • HFile(StoreFile)에 저장되는 인덱스는 랜덤 액세스를 지원하기 위해 Cell coordinates를 포함한다.

만약 coordinates(특히 Row Key나 Column Name)의 길이가 길다면

  • HBase 메모리(RAM)에서 인덱스를 유지하기 위해 큰 메모리 블록(Chunk)을 차지하게 된다.
  • 이로 인해 인덱스가 비대해지고, 메모리 자원 효율성이 떨어질 수 있다.

4.3.2 완화 방안

  1. Row Key & Column Name 최소화

    • 불필요하게 긴 문자열 대신 짧고 고정 길이의 identifier 사용
    • 예: user_information:name 대신 u:n
  2. StoreFile 블록 크기 조정

    • 인덱스 항목 생성 간격을 늘려, 메모리 점유를 줄인다.
    • 단, 블록 크기 증가는 I/O 성능에 영향을 줄 수 있으므로 workload 특성에 따라 튜닝 필요
  3. 압축 사용 시 주의

    • 압축은 저장 공간 효율은 높일 수 있으나,
    • 오히려 coordinates 인덱스를 상대적으로 더 크게 만들어 메모리 효율성을 해칠 수 있음

대부분의 경우 이러한 비효율성은 치명적이지 않다.
그러나 Column Family, Attributes, Row Key 설계 패턴은 데이터 전체에 걸쳐 수십억 번 반복되는 coordinates 구조에 영향을 주므로, 초기 설계를 잘하는 것이 장기적인 효율성에 큰 기여를 한다.

대부분은 키 사이즈 자체를 줄이는 것이 성능 향상에 가장 좋다.



4.4 Reverse Timestamps

HBase는 Row Key를 사전순(lexicographical order)으로 정렬한다.
이 특성을 활용하여 최신 데이터를 항상 앞쪽에 위치하도록 설계하는 방법이 Reverse Timestamp이다.

4.4.1 원리

Row Key의 끝부분에 Reverse Timestamp 값을 붙인다.

  • Reverse Timestamp = Long.MAX_VALUE - timestamp

rowkey = user_id + ":" + (Long.MAX_VALUE - timestamp)

이렇게 하면 동일한 user_id 안에서 최신 데이터가 가장 작은 값으로 평가되어 Row Key 순 정렬 시 앞쪽에 위치한다

4.4.2 장점

  1. 최신 데이터 우선 조회

    • 최신 레코드를 앞에서부터 빠르게 찾을 수 있다.
    • 예: Timeline 서비스, 최근 이벤트 로그 조회
  2. 과거 버전 유지 가능

    • HBase Cell 자체에도 versioning 기능이 있으나, 이는 보존 기간 및 설정값에 따라 제한된다.
    • Reverse Timestamp를 Row Key에 포함하면, 같은 Key 범위 내에서 과거 데이터를 정렬된 순서로 관리할 수 있다.
  3. Range Scan 최적화

    • 최신 데이터부터 특정 개수만 읽어오는 패턴(LIMIT N)에서 효율적이다.

4.4.3 한계 및 고려사항

  • Reverse Scan 지원 여부

    • HBase 0.98+ 부터는 Scan.setReversed(true) API가 제공된다.
    • 따라서 최신 버전에서는 굳이 Reverse Timestamp를 쓰지 않아도, 단순히 Row Key를 정상 timestamp로 저장한 뒤 Reverse Scan을 이용하면 된다.
    • HBase Scan.setReversed(boolean)
  • Row Key 길이 증가

    • Long.MAX_VALUE - timestamp는 64bit 숫자이므로 Row Key가 늘어나고, coordinates 크기 문제가 발생할 수 있다(→ 4.3 참고).
  • 범용성 부족

    • Reverse Timestamp는 "최신순으로 읽기"에 최적화된 기법이다.
    • 특정 시점 범위를 조회하는 경우, 오히려 정방향 timestamp 키보다 불편할 수 있다.

Reverse scan 을 지원하는 버전에서는 굳이 Reverse Timestamp 를 사용하지 않더라도 된다.

profile
Data Analytics Engineer 가 되

0개의 댓글