RDBを使わない究極のマルチテナント

takezaki
vtecx
Published in
7 min readSep 12, 2018

--

先日、SmartHRさんのDB移行の話が話題になりました。

これは、「つらくないマルチテナンシーをどのように実現したか」という生々しくインパクトのあるプレゼンでした。

ただ、個人的にはちょっと引っ掛かるところがありました。そもそもテナント毎にテーブルを作成するという設計に無理があったのではないかと思ったからです。Citus Cloudで解決できたそうなので結果オーライではあるのですが。

IBMの記事によるとマルチテナンシーのモデルには以下の3つがあるとのことです。

マルチテナントでDBを分けたくなる気持ちはわかります。②のパターンですね。

それは、顧客データを全て一つのDBに混ぜてしまうのはデータ混濁のリスクがあるのでDBの機能・ユーザーでデータを分離したいというのがその理由なのだろうと思います。

ですが、本当にDBを分ける必要があるかはよく考える必要があると思います。なぜなら、テナントごとに1 つのDBをサポートするという状態はマルチテナンシーが回避しようとしている非効率性を再び発生させるかもしれないからです。

テナントごとにスキーマが異なるケースならともかく、可能であれば③の単一DBで設計すべきだと思います。(単一DB共通スキーマ方式についてはよくまとまった記事があります)

さらにいうと、テナントごとにスキーマを分ける必要があっても単一DBを実現しているSalesforceがあります。Publickeyの記事によると、Salesforceはあらかじめ可変長文字列の列が501列用意されたテーブルを使って各テナントのスキーマに対応しているとのことです。

ただ、SalesForceはアプリケーションレイヤでのテナントのデータ分離について非常に強力なフレームワークを自社で構築しているからこそ③を選択できたともいえます。ごく普通の企業がSalesForceのようにできるわけもなく、とりあえず②でやろうという選択になりがちなのもわからないでもありません。

最も効率的なのは、アプリケーションがデータベースとアプリケーション・ビジネス・ロジックを完全に共有するモデルです。このモデルを実現するには、データベース・スキーマを変更してテナント ID をすべてのテーブルとビューに追加するだけでなく、あらゆる SQL アクセスを作成し直し、テナントの基準をフィルターに追加するという厄介なプロセスが必要になる可能性があります。コードでこれらの変更を加えなければならない箇所が 1 箇所でも見落とされると、アプリケーションのデータ・セキュリティーが危険にさらされる恐れがあります。 https://www.ibm.com/developerworks/jp/cloud/library/cl-multitenantsaas/index.html

究極のマルチテナントを実現するには

マルチテナントの目的はリソースの効率化です。必要性を突き詰めると、経済的であるということがマルチテナンシーにすべき第一の理由となっています。そして、サーバやDBを共有化して最も効率よく利用するモデルが③であり、IBMの記事でも「最も効率的な真のマルチテナンシー」と説明されています。

しかし、③のSalesforceのようなケースでは、ガバナ制限、つまり、多くのユーザがサーバやDBのリソースを共有しているので、自分の組織だけでそのリソースを食いつぶさないようにする制約を避けることができません。

また一方で、マルチテナントは「ベンダー側の都合」であり、ユーザーにとっては何らメリットはないという主張があります(マルチテナントに未来はあるか)

私はこの主張に賛成です。ユーザがクラウド上であってもいっそ自分専用のリソースを確保したい、あるいは他人の利用がいっさい自分たちのシステムに影響を与えないでほしいと思うのは当然のことであり、ガバナ制約なんてのは無いに越したことはありません。

なので、究極のマルチテナントとは、論理的に①を実現し、ガバナ制約のないスケーラブルで効率的なものであるべきだと私は考えています。

そのような究極のマルチテナントは実はRDBを使わないということで実現できます。Google DatastoreやCloudStorage、BigQueryなどのマネージドなサービスを利用するのです。

Cloud Datastore は分散アーキテクチャを使用して自動的にスケーリングします。そして、Namespaceでデータセットを分けることができます。Datastoreはスキーマレス(ソフトスキーマ)なので、アプリケーションにおいて項目の追加などがあってもマイグレーションする必要はありません。

また、CloudStorageは無限にスケールするストレージであり、Bucketごとに領域を区切ることができます。

マルチテナントにするには、サブドメインでテナント(サービス)を分け、NamespaceやBucketなどにサービス名をつけるだけです。

vte.cxでは、これらのマネージドサービスとkubernetesを利用することで、ガバナ制約のない究極のマルチテナントを実現しています。

ただ、BigQueryについてだけは、少し面倒ではありますが、テナントごとにサービスアカウントを作成してもらい、それを設定してもらうようにしています。

RDB神話を鵜呑みにしない

私達がRDBに寄せる信頼は絶大なものがあります。

一時期、NoSQLブームがあったものの、RDBはすべてのシステム開発の前提となっており、RDB抜きでアプリケーションを作るなんて想像し難いものがあります。

それは、この記事を読むとよくわかります。

2018年現在は、PostgreSQL 10やMySQL 8などRDBMS(以下、わかりやすくSQLと呼びます)でJSONをネイティブに扱える(インデックスを貼ったりツリーの一部を操作したり)のがスタンダードになったので、むしろこれらSQLのほうに勢いがあります。

・・・

それ以外の80%以上のユースケースでは、いまだSQLにまさるものはないでしょう。

しかし、マルチテナントをRDBでやるのはちょっと厳しいと思います。マルチテナントはたぶん、20%のユースケースの方に入るのでしょう。

SmartHRさんで利用されているCitusや、他にもNuoDB というものもあるようですが、実際に運用するとなると綱渡り感があって非常に危うい感じがします。それに、マイグレーション時間は短くなってはいますが、なくなるわけではありません。

vte.cxでは、数万件ぐらいのデータでトランザクション処理が求められるものについてはDatastoreを使い、履歴データなどについてはBigQueryを使うといった感じで使い分けています。このように、RDBがなくても普通に業務アプリケーションは作れるのです。

ここは思い切ってRDB以外の選択も考えるべきではと思う次第です。

--

--

顔がアイコンに似てますねといわれると喜びます。/ (株)コントラーズCTO/(有)バーチャルテクノロジー代表 / フロントエンドが主役のシステム開発を実現するバックエンドサービス vte.cxを作っています