僕の考えた最強のDB for 会員むけシステム

ソシャゲとかその他C2Bな会員向けシステムにとって最強のDBはどういうのだろうか? とTwitterでつらつら考えてたのでブログにもまとめ直してみる。

理想的なイメージは1会員で1DBを割り当てて全てストアドプロシージャで処理すること。 自分でユーザIDとかでシャーディングすればできなくは無い気がする。

こんな事が出来ると嬉しい

  1. テーブルのレコード単位で細かくロックを制御する必要は不要でテーブルを超えてユーザID単位でロックが掛かって欲しい
  2. データをDBサーバやアプリサーバに取得する処理が無駄なのでストアド的(というかイメージはSpark)にデータがあるストレージで処理して欲しい
  3. 上記を効率的に実現するためにユーザID単位のデータは全て同じストレージに居て欲しい。あとマスタテーブルは全てのストレージに居て欲しい
  4. ユーザ単位でロックを掛けると一部の処理は少し長めのとある処理より優先したい時はあるのでトランザクションを割り込ませて既存ロジックは再実行したい
  5. そうは言っても集計処理はしたいのでHANAがしてるみたいに分析が得意なDBにリアルタイム連携したい
  6. インサートやデリートでインデックスのロックとか他のレコードに影響を与えないで欲しい。

でもって以下のことは許容できる

  • 極端な低レイテンシーは要らない。ビジネスロジック混みで数百ms(もちろんロジック次第では数秒)程度で良い。
  • 強い一貫性の保証は同一ユーザIDのものだけで良い
  • 分析用DBへの連携は非同期で数秒程度の差分があっても大丈夫。どうせ集計だし
  • where句は無くても良い。キーアクセスだし。
  • ユーザ自体が瞬時に大量に増えた時にユーザ登録処理速度が低下するのは仕方ない。普通無いだろうし。

今の所イメージに一番近いのはAzureのCosmos DBの気がする。

GoogleのCloud Spannerはストアドは無いみたいだし。まあ、ストアド無くてもFunctionsとかで処理すれば関連するデータが同じストレージにあってJOINペナルティとかが無いならあまり問題にならないかも。ドキュメントDBだとユーザーの下が無限に増えるからストアド的なのが無いとやはり厳しいだろうけど。

ユーザ単位で処理を考えるとやっぱりドキュメントDBやオブジェクトDBのがしっくり来るなぁ。 基本的にはユーザ単位でアトミックでロックやトランザクションが効けば良くてデータが同じ箇所に集中してる必要があるとすると、データモデルはリレーショナルよりはオブジェクトモデルのが物理実体とも近いから作りやすそうだし。

○○なユーザを抽出って処理とかでユーザを跨ぐことはあるけどそれって結局抽出した後に集計するかユーザ単位に処理するかなので、 集計ならDWHで集計で良いし、最終的にユーザ単位の処理なら会員数分の並列で良い気がする。

こういう特製のデータベースってなんか無いだろうか?

自分で作るならsqliteあたりを包んだdockerコンテナを作ってユーザ毎にコンテナ作製して、ルーティングアプリを手前に置いてgRpcで通信すれば良さそう。 それならデータ量が多いユーザは別なPodへ移動させるとかも出来るから1ユーザーが1台のマシンのストレージを超える(インメモリでも数百GB、SSDとかならTBクラス))容量にならない限りは、この方式でスケールするから普通のシステムなら破綻はしなさそう。 その場合、DWHへの連携はトリガーを書きまくれば良いのかな?

ただ、詰まるところシャーディングだからテーブルスキーマの変更はちょいめんどそうかも。

でも、スキーマ変更をローリングでして困るケースも実はあんまり無い気がするので万能選手を期待しなければ結構良い感じになる気がしてきた。

まとめ

システムがデカくなるとデータが増えて処理性能が落ちるんだけど、本来ならばほとんどの処理は横にスケールする筈だよなぁ、と思って自分の理想の仕組みを考えてみました。

全く同じものは世になかったとしても、一回考えると今後の技術要件を探る時には役立ちそうですし。特にクラウド系分散DBは似たような課題をクリアしようとしてのものな気がするし。

それではHappy Hacking