Bigtable Authorized Viewを用いたスケーラブルなテナント分離アーキテクチャ

内製OLAP DBとBigtable Authorized Viewの活用


私たちが提供するKARTEでは、日々膨大な量のユーザーの行動データが取得され、取得したデータに対して分析が行われます。現在、毎月1ペタバイト(PB)強のデータがインサートされており、総データ量は8PB、月間解析量は180PBに達しています。

この膨大なデータを高速に分析するため、私たちはユーザーの行動データ分析に特化した内製OLAP DB「mila」を開発しています。

解析対象のデータは、弊社のリアルタイム解析基盤を通じてBigQueryに保存後、独自のパイプラインにより専用のフォーマットに変換されmilaのデータソースに永続化されます。

私たちは、このパイプラインの中間部分で使用する分散QueueとしてBigtableを使用しております。また、milaはマルチテナントなシステムであり、その中でデータの混在や権限面での事故を防ぐため、アプリケーション層ではなくインフラ層でのテナント分離を注力して行っています。(例えば、milaはGKE上でホスティングされており、k8sのnamespaceを利用してGKE上でのテナント分離を実現しています。)

そのため、Bigtableの使用においても、前述のような大量のデータ書き込み・読み取り性能を維持しつつ、数百規模のテナント間で分離されていることが求められます。これらを実現するアプローチとして、私たちはBigtable Authorized Viewの利用を検討しました。

本記事では、Bigtable Authorized Viewを用いたテナント分離の実現と、パフォーマンスの検証結果についてご紹介します。

データ同期パイプラインの全体像


まず初めに、Bigtableの使用箇所とユースケースを明らかにするため、データ同期パイプラインの全体についてお話しします。下の図がパイプラインの概略図になります。 図には、Google Cloudのリソースに加えて、二つのmilaのコンポーネントが存在しています。(BigQueryからのデータを受け取るIngester、データフォーマットの変換と永続化を行うIndexer)

データは以下の流れでBigQueryからmilaに同期されます。

  1. リアルタイム解析基盤を通じて解析対象のデータがBigQueryに格納されます。
  2. その後、新しいレコードはBigQueryのContinuous Queryによりインクリメンタルに抽出され、IngesterがSubscribeするPub/SubのTopicに転送されます。
  3. Pub/Subからデータを受け取ったIngesterは、次のコンポーネントであるIndexerに中継します。この時、書き込みをIndexerに知らせるために2で使用したPub/Subとは異なるPub/Subを用いています。
  4. Indexerは受け取った行データをmilaの内部フォーマットに変換し(Indexing処理)、データの本体をGoogle Cloud Storage、メタデータをSpannerにそれぞれ格納します。

ここで、IngesterとIndexerでの実際のデータの受け渡しとIndexerでの処理の失敗に備えた永続化のための分散QueueとしてBigtableを使用しています。

また、Bigtable以外のテナント分離についてですが、Google Cloudのリソースは基本的には別々で管理・作成し、データと権限の分離を行っています。milaのIngesterとIndexerに関しては、GKE上のnamespaceで隔離されたテナント間で異なるPodが動いています。

Bigtable Authorized Viewを用いたテナント分離


マルチテナント環境において、テナントごとに物理的なテーブルを作成する方法は、テーブル数が増加した際のパフォーマンス劣化や管理コストの増大から非推奨とされています。[1]

そのため、私たちは全てのテナントのデータを単一のBigtableテーブルに保存し、テナントごとに異なるBigtable Authorized Viewを用いてテナント分離を実現しました。

ここでは、分散QueueとしてBigtableを利用する行キーの設計について述べたのち、テナント分離のためのAuthorized Viewの活用についてお話しします。

行の設計

milaでは、全てのデータはテナントごとに分離されテナント内では特定のキー(ユーザーのIDなど)でシャーディングされ保存されます。

行キーの設計としては、特定テナントのデータアクセスの集中によるホットスポットを避けるため、以下のようにテナントのIDに加えて、シャードの値を入れたハッシュ値をプレフィックスに用いています。

Hash(tenantId + shard + tableId)::tenantId::tableId::shard::timestamp

シャード内でアクセスが集中した場合は、ホットスポットを避けることはできませんが、KARTEでは特定のユーザーで大量のデータが生成されるケースは、システムのバグを除き存在しないため上記のキーの設計で問題ありません。

Authorized View 活用とテナント分離方法

Authorized Viewでは、セキュリティとデータ分離を実現するために、以下の3つの方法でアクセス可能なデータの範囲を限定できます。[2]

  1. 行キーの接頭辞
  2. 列修飾子の接頭辞 または列修飾子
  3. 行キー接頭辞と列修飾子を組み合わせたもの

ここで、テナントIDを行キーの接頭辞(Keyの先頭)に使用してしまうと、前述の通り、特定のテナントにアクセスが集中した場合にホットスポットが発生する可能性があります。

そのため、私たちはこのリスクを避け、列修飾子の接頭辞を用いることでテナント分離を実現することにしました。これにより、Key全体は均等に分散されたままで、各テナントは自身のデータのみに安全にアクセスすることができるようになります。

Bigtable Authorized Viewの有無におけるパフォーマンスの検証


以上の構成を用い、Bigtable Authorized Viewを使用した場合と、使用しない通常アクセスの場合でパフォーマンスにどのような差が生じるかを検証しました。特に、想定される数百規模のテナントが同時にアクセスする環境下での影響を評価しています。

ワークロードの設定

複数のスレッドから各テナントのAuthorized Viewを経由したアクセス(書き込み/読み取り)と、Bigtableへの直接のアクセスをそれぞれ実行します。検証では同じインスタンスにアクセスを行い、Authorized Viewの有無によってアクセスするテーブルを分離しています。

ワークロードの数値は本番の状況を模したものであり、詳細は以下のとおりです。

  • 対象テナント数: 300
  • 1テナントあたりのスループット: 300 rows/sec (システム合計: 90k rows/sec)
  • 1テナントあたりのリクエスト: 50 req/sec (システム合計: 15k req/sec)
  • 1行当たりのデータサイズ: 0.5 KB

計測結果

Cloud Monitoringを用いて、CPU使用率およびレイテンシの分析を行った結果を示します。なお、レイテンシについてはp99(99パーセンタイル)の数値を採用しています。

メトリクスには、Cloud Monitoringの以下の指標を使用しました。

  • CPU使用率: bigtable.googleapis.com/cluster/cpu_load
  • レイテンシ: bigtable.googleapis.com/client/operation_latencies

次のグラフにおけるラベルは、それぞれ以下の測定対象を示しています。

  • bt-bench-auth : Authorized Viewを経由したBigtableへのアクセス
  • bt-bench-raw : Bigtableへの直接アクセス

CPU 使用率

Authorized Viewの有無によるCPU使用率において顕著な差は見られませんでした。負荷のスパイクも発生しておらず、Authorized Viewの導入がCPUの負荷に与える影響は軽微であると考えられます。

レイテンシ (Read / Write)

読み取り・書き込みともにAuthorized Viewを経由した方がわずかにレイテンシが高い、またはほぼ同等のパフォーマンスを示すことが確認できました。 双方の環境において局所的なレイテンシのスパイクが見えますが、その発生頻度や挙動に有意な差はありません。そのため、Authorized Viewの使用がレイテンシの安定性に影響を及ぼしていないと考えられます。

まとめ


本記事では、Bigtable Authorized Viewを用いたスケーラブルなテナント分離について、具体的なユースケースとパフォーマンス検証を交えて紹介しました。私たちは、データ同期パイプラインにおける分散キューとしてBigtableを採用し、マルチテナント環境での安全なデータ分離を実現するためにAuthorized Viewを活用しました。

パフォーマンス検証の結果、想定される数百規模(300テナント)の環境下においてもAuthorized ViewによるCPU使用率やレイテンシの劣化はほとんど見られませんでした。権限制御に伴うオーバーヘッドをほぼ無視して、数百規模のテナント分離を高いパフォーマンスのまま実現できる点は、非常に使いやすいと感じました。

また、追加の課金も発生しない点に加え、Authorized Viewを利用した権限制御は複数の方法で行うことができます。そのため、今回のテナント分離以外にも、細かいアクセス制御が求められるユースケースにおいてBigtable Authorized Viewは適していると考えます。

[1] https://docs.cloud.google.com/bigtable/docs/schema-design?hl=ja#multi-tenancy

[2] https://docs.cloud.google.com/bigtable/docs/authorized-views?hl=ja#view-definition