MongoDBを使わないでください:いや、使ってもいいです

MongoDBを使わないでください:いや、使ってもいいです

D
dongAuthor
2 min read

かつて開発コミュニティでは「MongoDBを使わないでください」という言葉が流行しました。スキーマがないという理由で、トランザクションのサポートが不足しているという理由で、多くの開発者がMongoDBを避けていたのです。しかし2024年現在、そうした偏見の多くは過去の話となっています。

Why You Should Never Use MongoDB

MongoDBは継続的な進化を通じてエンタープライズ級データベースに成長し、Stripeのように年間1兆ドルの決済を処理する企業でもコアインフラとして採用されています。本投稿では MongoDB がなぜ優れた選択肢なのか、そして実際の大規模サービスでどのように活用されているかを見ていきましょう。

「MongoDBを使わないでください」、今は違います

過去にMongoDBに対する批判は、ほとんどが初期バージョンの限界からきていました。スキーマ検証の欠如、ACIDトランザクション非対応、データの整合性問題などが主な論点でした。しかし現在、MongoDBはこれらの問題の多くを解消しています。

スキーマ検証のサポート:MongoDBは今ではスキーマ検証機能を提供しています。JSONスキーマを通じてデータ構造を強制でき、必要に応じてRDBMSに似た制約条件を設定できます。

トランザクションのサポート:4.2バージョンから完全なACIDトランザクションをサポートしています。もちろん大規模トランザクションではパフォーマンス低下が起こる可能性がありますが、これは他のデータベースでも同様です。

高可用性と整合性:Raftアルゴリズムに基づく自動障害復旧により、およそ1秒以内に復旧が可能であり、read/write concern設定を通じてデータ整合性とトラフィック分散を効率的に管理できます。

もはや MongoDB は「プロトタイプを素早く作るときだけ使うデータベース」ではありません。エンタープライズ環境でも十分に安定かつ拡張可能なソリューションになっています。

How Stripe’s document databases supported 99.999% uptime with zero‑downtime data migrations

TLA+ によって検証された MongoDB

TLA+(Temporal Logic of Actions Plus) は、分散システムのアルゴリズムを数学的に仕様化・検証するための言語です。簡単に言えば、複雑なシステムが意図どおりに動作するかを事前に検証できるツールですね。

MongoDB はこの TLA+ を用いて分散アルゴリズムを設計し、システムの正確性を保証しています。例えば、複数ノード間のデータ複製が正しく行われるか、障害時にデータ整合性が維持されるか、といったことをTLA+でモデリング・検証しています。

これは MongoDB がただ「素早く作られた」NoSQLデータベースではなく、数学的証明を通じて安定性を保証するエンタープライズ級システムであることを示します。TLA+ による検証は、MongoDB の分散システムアルゴリズムが理論的に信頼できることを示しています。

Conformance Checking at MongoDB: Testing That Our Code Matches Our TLA+ Specs

MongoDB のコア機能たち

ドキュメント志向構造

MongoDB はデータを JSON ドキュメント形式で保存します。これは内部的には BSON(Binary JSON)に変換されて処理されます。こうした構造はモダンなウェブアプリケーションと完全にマッチしています。

// MongoDB ドキュメントの例
{
  "_id": ObjectId("507f1f77bcf86cd799439011"),
  "name": "김개발",
  "email": "kim@example.com",
  "skills": ["JavaScript", "React", "Node.js"],
  "projects": [{  "name": "쇼핑몰 프로젝트",  "status": "완료",  "technologies": ["React", "MongoDB"]}
  ]
}

こうした入れ子になった構造を RDBMS で表現しようとすると、複数のテーブルと複雑な JOIN が必要になりますが、MongoDB では一つのドキュメントで簡潔に処理できます。

柔軟なスキーマ

スキーマが柔軟であるということは「スキーマが無い」という意味ではありません。必要に応じてスキーマを強制することもできるし、緩く管理することもできるという意味です。例えば、ユーザープロフィールデータで一部のユーザーは電話番号を持っていて、あるユーザーは持っていないこともあります。RDBMS では NULL を許可するか別テーブルを作る必要がありますが、MongoDB では自然に処理されます。

拡張性(シャーディング)

MongoDB のシャーディングは非常に強力な機能です。データを複数のサーバーに自動的に分散し、水平スケーリングを可能にします。シャードクラスターは以下の構成要素で構成されています:

  • mongos:クエリを適切なシャードにルーティング
  • config servers:メタデータを管理
  • shard nodes:実際のデータ保存

シャードキーを通じてデータを分散させることで、効率的なクエリ処理と拡張が可能です。ですが、シャードキーの選び方を誤ると性能低下やデータ不均衡を招くため、慎重に設計する必要があります。

多様なインデックス機能

MongoDB は B‑Tree ベースの単一フィールドインデックスから、複合キー、マルチキー、地理空間、ハッシュ、テキストインデックスまで多様なインデックスをサポートします。特に地理空間インデックスは S2Geometry ライブラリを使って位置情報データを効率的に処理できます。

// 地理空間インデックス作成の例
db.places.createIndex({ "location": "2dsphere" })

// 半径1km以内検索
db.places.find({
  location: {$near: {  $geometry: { type: "Point", coordinates: [127.0276, 37.4979] },  $maxDistance: 1000}
  }
})

Stripe も MongoDB を積極的に使用しています

Stripe の事例は MongoDB がエンタープライズ環境でどれほど強力かを示す完璧な例です。2023年、Stripe は年間1兆ドルの決済を処理しながら、99.999%の稼働率を維持しました。

How Stripe’s document databases supported 99.999% uptime with zero‑downtime data migrations

DocDB:MongoDB ベースのカスタムソリューション

Stripe は MongoDB Community を基盤として DocDB という独自データベースインフラを構築しました。DocDB は一秒間に500万件以上のクエリを処理し、Stripe のすべての製品アプリケーションを支えています。

Stripe が MongoDB を選択した理由は次の通りです:

  1. ドキュメントモデルの柔軟性:複雑な決済データ構造を自然に表現
  2. 大規模リアルタイムデータ処理能力:一秒間あたり数百万件のトランザクション処理
  3. 開発者の生産性向上:RDBMS に比べて高速な開発速度

無停止データマイグレーション

Stripe の最も印象的な実績のひとつが無停止データマイグレーションです。Data Movement Platform を通じてサービス停止なしでデータを移行できます。このシステムは次のようなステップで動作します:

  1. マイグレーション登録:チャンクメタデータサービスへのマイグレーション意図登録
  2. 大量データの取り込み:スナップショットを用いた最適化されたデータ読み込み(10倍性能向上)
  3. 非同期複製:Kafka と Amazon S3 を活用したリアルタイム同期
  4. 正確性チェック:データの完全性と正確性検証
  5. トラフィック切り替え:2秒以内に完了する無停止切り替え

このようなシステムを通じて、Stripe はトラフィック急増時にシャードを分割し、トラフィックが少ない時に数千のデータベースを統合できます。

プロキシサーバを通じた信頼性の確保

Stripe は Go 言語で開発した独自のデータベースプロキシサーバを通じて、信頼性、拡張性、アクセス制御を管理しています。これは MongoDB 自体の機能に加えて、エンタープライズ級要求を満たす方法です。

MongoDB のメリットたち

性能優秀性

MongoDB は特定の使用ケースで優れた性能を発揮します。Cars24 の場合、MongoDB Atlas を用いて3億人のユーザー向けの検索サービスを改善し、コストを半減させました。

MongoDB Atlas Search を通じてデータベース内で直接検索クエリを実行できるため、別途検索エンジンとデータ同期を行う必要がなくなりました。これはリアルタイム検索結果を提供しつつ、アーキテクチャを簡素化しています。

高可用性

MongoDB のレプリカセットは自動障害復旧を提供します。プライマリノードに問題が発生すると、約1秒以内にセカンダリノードがプライマリノードの役割を引き継ぎ、サービス停止を最小限に抑えます。これは Raft アルゴリズムに基づく検証済みの方式です。

利用のしやすさ

MongoDB Query Language(MQL)は JavaScript ベースで、ウェブ開発者にとって親しみがあります。JSON と類似した文法を使うことで学習曲線が緩やかです。

// ユーザー検索の例
db.users.find({
  $and: [{ "age": { $gte: 18 } },{ "skills": { $in: ["JavaScript", "React"] } },{ "location.city": "서울" }
  ]
}).sort({ "createdAt": -1 }).limit(10)

統合された開発体験

Cars24 の例に見られるように、MongoDB Atlas はデータ保存と検索機能を一つのプラットフォームで提供します。開発者は別のツールや同期を意識せず、単一の API で全ての操作を処理できます。

これは開発者がインデックス管理やデータ同期よりも、アプリケーション開発と製品構築に集中できるようにします。

素早い開発者オンボーディング

MongoDB に慣れた開発者を迅速にチームに迎え入れることができます。これは特にスタートアップや急成長中の組織で重要なメリットです。

実際の使用時に考慮すべき点

MongoDB を使用する際に注意すべき点も存在します:

JOIN の代わりにデータ重複

MongoDB は伝統的な JOIN をサポートしません。$lookup 演算子を使えますが、RDBMS の JOIN に比べて性能が落ちることがあります。したがって、必要なデータを事前に重複保存することが推奨されます。

トランザクション使用を最小化

トランザクションをサポートしていますが、大規模トランザクションでは性能低下を起こす可能性があります。可能であれば埋め込みドキュメント構造を使用して、トランザクションの必要性を減らしたほうが良いでしょう。

シャードキー選択の重要性

誤ったシャードキーの選択は性能低下とデータ不均衡を招きます。シャードキーはクエリパターンとデータ分散を考慮して慎重に選ぶべきです。

References