MongoDBのシャーディング(分片)は、データの増大に伴い単一のサーバーではストレージ容量や処理能力が不足する場合に、データを複数のサーバーに分散させることで水平スケーリングを実現する技術です。
シャーディングが必要となる背景
データ量やトラフィックが増加すると、以下のような課題に直面します。シャーディングはこれらの問題を解決するために導入されます。
- 書き込み負荷の集中: すべての書き込みがプライマリノードに集中し、パフォーマンスが低下する。
- メモリ不足: ワーキングセットが物理メモリに収まらなくなり、ディスクI/Oが増大する。
- ストレージの限界: 単一マシンのディスク容量を超えたデータ保持が必要になる。
- コスト効率: 高性能な単一サーバー(垂直スケーリング)を導入するよりも、安価なサーバーを並列化する方がコストを抑えられる。
クラスターを構成する主要コンポーネント
MongoDBのシャーディング環境は、主に以下の3つの要素で構成されます。
1. シャード (Shard)
実際にデータを保持するコンポーネントです。可用性を高めるため、本番環境では各シャードをレプリカセットとして構成するのが一般的です。
2. 設定サーバー (Config Server)
クラスターのメタデータ(どのデータがどのシャードにあるか等)を管理するサーバーです。クラスター全体の構成情報を保持する重要な役割を担います。
3. クエリールーター (mongos)
アプリケーションとクラスターの仲介役となるインターフェースです。アプリケーションからは単一のデータベースのように見え、mongosが適切なシャードへリクエストを振り分けます。
シャーディングの構築手順
以下に、基本的なシャーディング環境を構築する流れを説明します。ここではテスト環境を想定し、異なるポートで各プロセスを起動します。
手順1:シャードサーバーの起動
まず、データを保存する複数のmongodインスタンスを起動します。
# データディレクトリの作成
mkdir -p /data/shard/rs0_1
mkdir -p /data/shard/rs0_2
# インスタンスの起動
mongod --shardsvr --port 30001 --dbpath /data/shard/rs0_1 --logpath /data/shard/rs0_1.log --fork
mongod --shardsvr --port 30002 --dbpath /data/shard/rs0_2 --logpath /data/shard/rs0_2.log --fork
手順2:設定サーバーの起動
次に、クラスター情報を管理する設定サーバーを起動します。
mkdir -p /data/shard/config
mongod --configsvr --port 40001 --dbpath /data/shard/config --logpath /data/shard/config.log --fork
手順3:クエリールーター (mongos) の起動
設定サーバーを指定して、ルータープロセスを立ち上げます。
mongos --configdb localhost:40001 --port 50000 --logpath /data/shard/mongos.log --fork
手順4:クラスターへのシャード追加と有効化
mongosに接続し、各ノードをシャードとして登録します。
# mongosへ接続
mongo --port 50000 admin
# シャードの追加
db.runCommand({ addshard: "localhost:30001" })
db.runCommand({ addshard: "localhost:30002" })
# データベースのシャーディング有効化
db.runCommand({ enablesharding: "app_db" })
# コレクションに対してシャードキーを設定しシャーディングを開始
db.runCommand({ shardcollection: "app_db.orders", key: { "order_id": 1, "created_at": 1 } })
レプリカセットを用いた高度な構成
可用性を重視する場合、各シャードおよび設定サーバー自体をレプリカセットとして構成します。
設定サーバーのレプリカセット化
# 設定サーバー1, 2の起動
mongod --configsvr --replSet cfs --port 40001 --dbpath /data/conf1 --fork --logpath /data/conf1.log
mongod --configsvr --replSet cfs --port 40002 --dbpath /data/conf2 --fork --logpath /data/conf2.log
# 初期化 (mongo shellより)
rs.initiate({
_id: "cfs",
configsvr: true,
members: [
{ _id: 0, host: "localhost:40001" },
{ _id: 1, host: "localhost:40002" }
]
})
ルーターからの接続設定
レプリカセット形式の設定サーバーを指定してmongosを起動します。
mongos --configdb cfs/localhost:40001,localhost:40002 --port 50000 --fork --logpath /data/mongos.log
このようにシャーディングを構成することで、アプリケーション側のコードを大きく変更することなく、データベース層の容量とスループットを動的に拡張することが可能になります。