Lapis Lazuli

technical blog for web developer

Spannerを使ってみて大体の感想

久しぶりの更新になります。今回はGCPのCloudSpannerについてです。
決してサボっていた訳ではありません。仕事が・・・というよくあるやつです。

CloudSpannerとは

GCPが誇る分散型データベースです。
なんと言っても最大の特徴は、ノードを増やすことでスループットをリニアに向上させることが出来ることです。
ここで「ん?」と思った方もいるかもしれません。
そう、スケールを無停止で出来るデータベースはDynamoDBとかが既に存在しています。
ではSpannerは何がすごいのかと言うと、RDBでこれを実現した事です。
オートスケールなDBって基本的にNoSQLなんですよね。KVSとか。
でもSpannerはデータ構造はRDBのままです。なので既存のアプリケーションから移行しやすかったり、エンジニアも開発しやすかったりします。
ただ、全てが同じという訳ではなく、独特の構造上の制限があるので、そこを意識しないといけません。
逆に言うと、ポイントさえ押さえればスケール出来るRDBという武器が手に入るんですけどね。

Spannerのしくみ

まず一般的なDBだとこういう構造になると思います。(図はAuroraで考えています)

f:id:cres-tech:20210313211014p:plain
RDB

エンドポイント経由でマスターにWriteを行い、ROに読み込みにいき、バイナリログを送る事で同期する
フェイルオーバー時にマスターと入れ替わるという、ごく一般的な構造のDBです。
これの問題はデータのWriteがマスターにしかできないことですが、これはRDBの構造を考えれば、ごく当たり前の事です。
テーブル同士の密接な関係にあるので、1箇所に保存するしかないからです。

しかしSpannerはこれを下記のようにすることで問題をクリアしています。

f:id:cres-tech:20210313213357p:plain
Spanner

まずRead/Writeなどの情報はClientが一括して受け持ちます。
一つのSpannerインスタンスに一つのClientが存在しており、完全マネージドで動いています。なので普段これを意識することはありません。
次にノードという、実際の処理を行う基盤があります。
更にノードの紐付けされているsplitという実データが保存されているものが複数に分かれている構造になっています。
これがspannerの肝となる構造で、split単位で保存するからこそ、分散型DBとして機能しているのです。

split構造と注意点

一つのsplitは一つのノードに紐付けされており、図のように複数のsplitをノードは管理しています。

splitがどのように分割されて保存されるかはユーザー側は知り得る事はありません。自動的に保存先が割り振られます。
ただ近いPK同士は同じsplitに保存されるようで、この仕組み上、PKをauto incrementなどで連番で発番すると負荷が一つのノードに集中してしまいます。
これを防ぐ為に、PKはUUIDを使う事がスタンダードなやり方です。
ランダムにすることで保存先splitを分散させているんですね。

インターリーブ

spannerはjoinを使ってテーブル結合を行う事が出来ません。その代わりにインターリーブという機能があります。
これは他テーブルのカラムを自テーブルに取り込む機能で、同じsplit内に保存されるようになります。
分散型とはあえて逆をいく局所的な保存をすることで、無駄に他splitにデータが分散されてパフォーマンス劣化する事を抑えている形になります。

使ってみてまとめ

RDBの構造のまま分散化が出来るようになった夢のようなDBだと言われますが、上記の癖ゆえ、既存のMySQLなどをそのまま置き換えるのは不可能です。
特性を理解して構築すれば素晴らしいDBですが、従来のDB感覚で設計してしまうとホットスポットの原因になると思いました。
特にPKを連番にすると分散化がまったく活かせなくなるので注意が必要です。
気をつけないといけないポイントはありますが、今後どんどん改良され、料金も安くなっていくのかなーと思いますので期待ですね。