FerretDBのセットアップ:PostgreSQL上でMongoDBを動かしてインフラを最小化する究極のテクニック

Database tutorial - IT technology blog
Database tutorial - IT technology blog

管理の悩み:データベースが増えすぎてインフラが肥大化するとき

想像してみてください。プロジェクトがPostgreSQL上で複雑な金融取引を円滑に処理しているとします。突然、チームが柔軟なログやメタデータの保存モジュールを追加する必要が生じ、MongoDBが導入されました。その結果、わずかなニーズを満たすためだけに、2つの異なるデータベース管理システム(DBMS)を運用、監視、バックアップしなければならなくなります。

これら2つの巨人を並行して運用すると、最小構成のインスタンスでも少なくとも2〜4GBのRAMを消費します。DevOpsエンジニアにとって、セキュリティプロセス、権限管理、バックアップ戦略を二重に行う必要があるのはまさに悪夢です。さらに、MongoDBがSSPLライセンスに移行したことで、コストと長期的な自由度の問題はかつてないほど頭の痛い課題となっています。

なぜMongoDBをやめるのが難しいのか?

なぜ最初からPostgresのjsonbを使わなかったのでしょうか?その答えはMongoDBドライバーにあります。コードのロジックはすでにNoSQLの構文と密接に結びついており、純粋なSQLへの変換はアプリケーションにとって「心臓手術」のようなものです。非常に時間がかかり、リスクも伴います。

MongoDBを削除するということは、数千行のコードをリファクタリングすることを意味します。一方で、PostgreSQLはJSONの処理には優れていますが、MongoDBアプリケーションが理解する言語(ワイヤープロトコル)で通信することはできません。MongoからSQLへのコマンドを一瞬で変換できる「通訳」が必要なのです。

エンジニアのための3つの一般的な選択肢

この状況から脱却するために、多くの場合は以下の3つの道を選びます:

  • 現状を受け入れる: 両方を並行して実行し続けます。この方法は安全ですが、サーバーのRAMとCPUを非常に多く消費します。
  • 全面的に書き直す: Postgresのjsonbを使用するようにロジックをゼロから作り直します。これが最もクリーンな方法ですが、数週間、あるいは数ヶ月の工数がかかります。
  • FerretDBを導入する: 中間的でありながら非常に効果的な解決策です。既存のコードはそのままに、MongoDBドライバーを使い続けながら、実際のデータはPostgreSQLに保存されます。

FerretDB:PostgreSQLがMongoDBに「なりすます」とき

FerretDB(旧名:MangoDB)は、プロキシ層として機能するオープンソースプロジェクト(Apache 2.0)です。それ自体はデータを保存せず、MongoDBのクエリをPostgreSQLのSQLに変換する役割だけを担います。

FerretDBは、極めて安定したPostgresの基盤上でドキュメント指向データベースの柔軟性を活用できるようにする架け橋です。JSON操作の快適さを損なうことなく、ACID特性による絶対的な信頼性を手に入れることができます。

Docker ComposeでFerretDBを高速セットアップ

テストとして、PostgreSQL 16と、その前段に配置するFerretDBの構成を構築します。システムが準備できるまで、わずか2分ほどです。

version: '3.8'

services:
  # メインのデータベースバックエンド
  postgres:
    image: postgres:16
    container_name: postgres
    environment:
      POSTGRES_USER: ferretuser
      POSTGRES_PASSWORD: secretpassword
      POSTGRES_DB: ferretdb
    ports:
      - "5432:5432"

  # FerretDBプロキシ
  ferretdb:
    image: ghcr.io/ferretdb/ferretdb:latest
    container_name: ferretdb
    restart: always
    environment:
      FERRETDB_POSTGRESQL_URL: "postgres://ferretuser:secretpassword@postgres:5432/ferretdb"
    ports:
      - "27017:27017" # MongoDBの標準ポート
    depends_on:
      - postgres

docker-compose.ymlファイルの準備ができたら、以下のコマンドを入力して起動するだけです:

docker-compose up -d

mongoshによる接続確認

伝説的なツールであるmongoshを使用して、実際のテストを行います。本物のMongoDBインスタンスに接続しているのと全く同じように動作することがわかります:

mongosh "mongodb://127.0.0.1:27017/"

コレクションにレコードを追加してみます:

db.itfromzero.insertOne({ 
  name: "FerretDB Tutorial", 
  type: "Database Proxy", 
  save_cost: "50% RAM"
});

db.itfromzero.find().pretty();

秘密はここにあります。pgAdminを使用してPostgreSQLデータベースを確認すると、FerretDBが自動的にテーブルを作成し、jsonbカラムにデータを投入しているのがわかります。すべてが完全に自動かつ透過的に行われます。

本番環境への導入時に注意すべき「落とし穴」

非常に便利ではありますが、FerretDBはあらゆるケースに対応できる銀の弾丸ではありません。移行前に以下の3つのポイントをよく確認してください:

  1. 互換性: 現在、FerretDBはワイヤープロトコル 5.0以降を良好にサポートしていますが、複雑すぎる集計(Aggregation)演算子は100%動作しない可能性があります。定期的に公式のロードマップを確認してください。
  2. パフォーマンス: プロキシ層を経由するため、わずかな遅延(レイテンシ)は確実に発生します。一般的なCRUDアプリであれば問題ありませんが、高トラフィックなアプリの場合は慎重にベンチマークを行う必要があります。
  3. インデックス管理: FerretDBは自動的にインデックスをマッピングしますが、Postgres上で手動で最適化するほど効率的ではない場合があります。Postgres側でのスロークエリ(Slow Query)の監視を忘れないでください。

要約すると、既存のコードに手を加えずにインフラを最小化し、データを一箇所にまとめて管理しやすくしたい場合、FerretDBは非常に賢明な選択肢です。不必要な肥大化したDBクラスターの運用からあなたを解放してくれます。

Share: