はじめに
昨今、TiDB や CockroachDB など、分散データベースが話題になることが増えてきました。スケールアウトできる高可用性のメリットが注目されますが、分散データベースを運用する上で避けて通れない問題があります。それがホットスポットです。
今回は、ホットスポットとは何か、なぜ分散データベースで問題になるのかについて触れていきたいと思います。
ホットスポットとは何か
ホットスポットとは、分散システムにおいて特定のノードやパーティションにアクセスが集中してしまう現象です。
分散データベースは、データを複数のノードに分散させることで、負荷を分散しスケーラビリティを実現します。理想的には、すべてのノードが均等に負荷を受け持ち、ノードを追加すれば線形にスループットが向上するはずです。
しかし、ホットスポットが発生すると話が変わります。特定のノードに負荷が集中し、そのノードがボトルネックとなってしまいます。せっかく 10 台のノードがあっても、1 台に負荷が集中していれば、残りの 9 台はほぼ未使用な状態です。これでは分散データベースの恩恵を受けられません。
なぜ分散データベースでホットスポットが発生するのか
パーティションキーの設計ミス
最も一般的な原因は、パーティションキーの設計です。
連番 ID(AUTO_INCREMENT)の罠
多くの RDBMS で馴染み深い連番 ID ですが、分散データベースでは問題になります。分散データベースは、ID の範囲でパーティションに分割されます。連番 ID の場合新しいレコードは常に最大の ID を持つため、書き込みが常に同じパーティションに集中します。
例えば以下のような SQL は分散データベースだとアンチパターンとなってしまいます。
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
);
タイムスタンプベースのキー
ログやイベントデータでよく使われる created_at をキーにすると、連番 ID と同じように最新のデータへの書き込みが常に同じパーティションに向かいます。
現実のワークロードは本質的に偏っている
設計が完璧でも、現実のアクセスパターンには偏りがあります。
- EC サイト
- セール開始時に特定商品へのアクセスが爆発的に増加
- SNS
- インフルエンサーの投稿は一般ユーザーの何万倍もアクセスされる
- 金融
- 取引量の大部分は特定の銘柄に集中している
ユーザー ID でパーティショニングしていても、人気ユーザーのデータを持つノードには負荷が偏ります。これは設計では防ぎきれない、ワークロードの本質的な特性です。
新規テーブル作成時の初期状態
多くの分散データベースでは、新しく作成されたテーブルはデフォルトで 1 つのパーティションしか持ちません。データが増えれば自動的に分割されますが、それまでの間は全ての書き込みが 1 つのノードに集中します。
大量データの初期ロードや、リリース直後のアクセス集中時にこの問題に直面することがあります。
一般的な対策
ホットスポットへの対策として、以下のような手法がよく知られています。
UUID / ランダムキーの使用
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255)
);
UUID はランダムに生成されるため、書き込みが自然に分散します。ただし、範囲クエリが非効率になるトレードオフがあります。
ハッシュパーティショニング
キーをハッシュ化してパーティションを決定する方法です。偏りのあるキーでも、ハッシュ後は均等に分散されます。
ソルティング
ホットキーに対して、ランダムな接頭辞や接尾辞を付加する手法です。
元のキー: user_123
ソルト後: 0_user_123, 1_user_123, 2_user_123, ...
書き込みは分散されますが、読み取り時には全てのソルト値を検索する必要があり、複雑さが増します。
Pre-Split
テーブル作成時に予めパーティションを分割しておく方法です。多くの分散データベースがこの機能を提供しています。
まとめ
ホットスポットは分散データベースにおいて避けて通れない問題です。
分散データベースを採用する場合には、パーティションキーの設計を注視すると良いでしょう。
ただ、現実のワークロードには偏りがあります。人気コンテンツ、アクティブユーザー、ピーク時間帯などなどなど……。
これらを完全に均等化しようとするのではなく、偏りの存在を前提としたシステム設計が求められています。
ワークロードの特性と、データベースの特性を理解した上で、適切な選択をすることが大切かと思います。