UUID符号空間を等分割して使う

概要

  • 16進表記のUUIDの符号空間は 00000000-0000-0000-0000-000000000000 ~ ffffffff-ffff-ffff-ffff-ffffffffffffで表せる
  • HBaseのテーブルのRow Keyが ${prefix}${区切り文字}${16進表記UUID} のような形式になっているような場合、${prefix}${区切り文字} ~ ${prefix}${${区切り文字のbyte値}+1}の間をSCAN操作することで${prefix}に属する全てのUUIDを一度にSCANすることができる。
  • しかし、一度にSCANする対象になるキーの数がはるかに大きい場合、符号空間を適切に分割した範囲で分割してSCANすることで、分割した範囲ごとに並列処理を行うことや、HBaseに対する負荷の軽減が期待できる。
  • 今回は、UUIDのケースに限って、クライアント側でSCANするキーの符号空間を適切に分割して返すコードを記述した。

実装方法

キー領域をDFSのように深掘りして分割していく。 HBaseのKeyはstopKeyがexclusiveなので、最終的に分割された領域のstopKeyのbyte値を+1をしたものをstopKeyとして使えば良い。 x個の領域に分割したい場合、n (2 ^ a and n >= x) のn個の領域に分割される事になる。

f:id:dasshshsd:20200929210704p:plain
分割イメージ

実装

gist.github.com

注意点

Javaでの処理とHBaseに格納する文字列のエンコーディングUTF-8を使用するものとする。ここで、'a'という文字が'9'という文字の値より大きいことを確認する必要がある。 (分割した領域でキーの値が単調増加する必要がある為)

assertThat('a' > '9').isTrue();

発展

  • なお、決められた符号空間によって表現されるRow Keyであれば、UUIDだけでなく他のものも同様の方法で分割できるような場合がある。
  • 実際には、負荷が高いSCANを行う場合にはMapReduceを検討すべきだが、クライアント側での分割SCANは柔軟性が高く、導入コストが楽である。
  • HBaseテーブルのRow Key Pre-Splitのように、事前に分割数が固定されていれば、最初から分割したキー領域を定義しておくことでより詳細に範囲を定めておくことが可能であるが、汎用的な分割数に対応することは難しい。