今更というネタでもありますが物理的に3台のマシンを使ってMongoDBのクラスタを組んだのでメモ
シャーディングとレプリカセットの組み合わせです
各ノードのIPアドレスとポートの例
IPアドレス
ノード名 | db1 | db2 | db3 |
---|---|---|---|
IPアドレス | 192.168.0.11 | 192.168.0.12 | 192.168.0.13 |
各サービス毎の利用ポート
ノード名 | db1 | db2 | db3 |
---|---|---|---|
config | 27018 | 27018 | 27018 |
mongos | 27017 | 27017 | 27017 |
shard1 | 27021 | 27021 | 27021* |
shard2 | 27022* | 27022 | 27022 |
shard3 | 27023 | 27023* | 27023 |
- レプリカセットのshard(x)の後ろに*があるのはArbiter(実データは持たずプライマリノードの選挙権だけを持つ)の意味
- 各ノードではconfig/shard1/shard2/shard3の4つのmongodプロセスとmongosプロセスが1つ動いてることになる
- クライアントアプリを各ノードのローカルに配布した場合、mongodb://localhost:27017/your_database で接続できる
- configサーバのレプリカセットにArbiterは存在できない
3台で同じ設定すんのめんどくせー
Ansibleで自動化したり、ディスクや仮想マシンのコピーができるクラウドサービスとか使うと捗ります
私もとあるイベント行ったときにもらったさくらのクラウドの無料枠でやりました
OS側の設定
MongoDBのインストール
この辺を参考にしてください(自演)
/etc/hostsの設定
IP直打ちだとノードがお亡くなりになったときに困ることも出てくるのでhostsで名前で引けるように追記して設定
192.168.0.11 db1
192.168.0.12 db2
192.168.0.13 db3
firewalldの設定
各ノード同士で接続できるようにポートをあけます
今回はスイッチの下で直接インターネットにはつながないマシンなのでガバガバ設定
firewall-cmd --permanent --zone=public --add-port=27017/tcp
firewall-cmd --permanent --zone=public --add-port=27018/tcp
firewall-cmd --permanent --zone=public --add-port=27021/tcp
firewall-cmd --permanent --zone=public --add-port=27022/tcp
firewall-cmd --permanent --zone=public --add-port=27023/tcp
firewall-cmd --reload
データ領域用のレプリカセットを作成する
データディレクトリの作成
デフォルトの場所とはちょっと違うところに各シャード用のデータベースのディレクトリを掘っておきます
プロセスを実行するユーザ mongod をオーナーにしてください
mkdir /data
mkdir /data/log
mkdir /data/mongoc
mkdir /data/shard1
mkdir /data/shard2
mkdir /data/shard3
chown mongod:mongod /data/log
chown mongod:mongod /data/mongoc
chown mongod:mongod /data/shard1
chown mongod:mongod /data/shard2
chown mongod:mongod /data/shard3
pidファイル置き場の作成
既にあれば不要
mkdir /var/run/mongodb
chown mongod:mongod /var/run/mongodb
データ領域用の設定ファイル
せっかくのMongoDB 3.2なのでWiredTigerで作ります
1つ作ってしまえばあとはコピペでほぼ大丈夫
各パラメータ(特にcacheSizeGBあたり)はサーバスペックに合わせて調整が必要
# shard1.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /data/log/shard1.log
logRotate: rename
# Where and how to store data.
storage:
dbPath: "/data/shard1"
engine: wiredTiger
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
statisticsLogDelaySecs: 0
collectionConfig:
blockCompressor: "snappy"
indexConfig:
prefixCompression: true
journal:
enabled: true
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/shard1.pid # location of pidfile
# network interfaces
net:
port: 27021
#security:
#operationProfiling:
replication:
replSetName: "shard1"
sharding:
clusterRole: "shardsvr"
## Enterprise-Only Options
#auditLog:
#snmp:
# shard2.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /data/log/shard2.log
logRotate: rename
# Where and how to store data.
storage:
dbPath: "/data/shard2"
engine: wiredTiger
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
statisticsLogDelaySecs: 0
collectionConfig:
blockCompressor: "snappy"
indexConfig:
prefixCompression: true
journal:
enabled: true
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/shard2.pid # location of pidfile
# network interfaces
net:
port: 27022
#security:
#operationProfiling:
replication:
replSetName: "shard2"
sharding:
clusterRole: "shardsvr"
## Enterprise-Only Options
#auditLog:
#snmp:
# shard3.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /data/log/shard3.log
logRotate: rename
# Where and how to store data.
storage:
dbPath: "/data/shard3"
engine: wiredTiger
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
statisticsLogDelaySecs: 0
collectionConfig:
blockCompressor: "snappy"
indexConfig:
prefixCompression: true
journal:
enabled: true
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/shard3.pid # location of pidfile
# network interfaces
net:
port: 27023
#security:
#operationProfiling:
replication:
replSetName: "shard3"
sharding:
clusterRole: "shardsvr"
## Enterprise-Only Options
#auditLog:
#snmp:
systemdの設定
yumでインストールするとCentOS7の場合でも/etc/init.d/*なスクリプトを経由することになるようなのですが、ここはCentOS7とsystemdの流儀に従ってsystemdのサービスを定義してみます
これも1個作ってコピペしてましたがスクリプト化するのがいちばん手っ取り早いかもしれない
[Unit]
Description=High-performance, schema-free document-oriented database
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=--quiet -f /etc/shard1.conf"
ExecStart=/usr/bin/mongod $OPTIONS
PIDFile=/var/run/mongodb/shard1.pid
[Install]
WantedBy=multi-user.target
[Unit]
Description=High-performance, schema-free document-oriented database
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=--quiet -f /etc/shard2.conf"
ExecStart=/usr/bin/mongod $OPTIONS
PIDFile=/var/run/mongodb/shard2.pid
[Install]
WantedBy=multi-user.target
[Unit]
Description=High-performance, schema-free document-oriented database
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=--quiet -f /etc/shard3.conf"
ExecStart=/usr/bin/mongod $OPTIONS
PIDFile=/var/run/mongodb/shard3.pid
[Install]
WantedBy=multi-user.target
設定が終わったら
systemctl daemon-reload
で設定ファイルの更新を反映させて起動
systemctl start shard1.service
systemctl start shard2.service
systemctl start shard3.service
データ領域のレプリカセット
各レプリカセットをMongoDB上で設定します
mongo db1:27021
shard1 > config = {
_id: 'shard1',
members: [
{_id: 0, host: 'db1:27021'},
{_id: 1, host: 'db2:27021'},
{_id: 2, host: 'db3:27021', arbiterOnly: true}
]};
shard1 > rs.initiate(config)
mongo db2:27022
shard2 > config = {
_id: 'shard2',
members: [
{_id: 0, host: 'db2:27022'},
{_id: 1, host: 'db3:27022'},
{_id: 2, host: 'db1:27022', arbiterOnly: true}
]};
shard2 > rs.initiate(config)
mongo db3:27023
shard3 > config = {
_id: 'shard3',
members: [
{_id: 0, host: 'db3:27023'},
{_id: 1, host: 'db1:27023'},
{_id: 2, host: 'db2:27023', arbiterOnly: true}
]};
shard3 > rs.initiate(config)
データ置き場はこれで3つのパーティション、各パーティションはPrimaryとSecondary2台のディスク+Arbiterの構成になりました
configサーバの設定
configサーバ用の設定ファイルを作成して
# mongoc.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /data/log/mongoc.log
# Where and how to store data.
storage:
dbPath: /data/mongoc
engine: wiredTiger
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
statisticsLogDelaySecs: 0
collectionConfig:
blockCompressor: "snappy"
indexConfig:
prefixCompression: true
journal:
enabled: true
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/mongoc.pid # location of pidfile
# network interfaces
net:
port: 27018
#security:
#operationProfiling:
replication:
oplogSizeMB: 64
replSetName: mongoc
sharding:
clusterRole: configsvr
## Enterprise-Only Options
#auditLog:
#snmp:
サービス設定を書いて
[Unit]
Description=High-performance, schema-free document-oriented database
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=--quiet -f /etc/mongoc.conf"
ExecStart=/usr/bin/mongod $OPTIONS
PIDFile=/var/run/mongodb/mongoc.pid
[Install]
WantedBy=multi-user.target
systemdに認識させてプロセスを起動
systemctl daemon-reload
systemctl start mongoc.service
次にレプリカセットを構成
mongo db1:27018
mongoc > config = {
_id: 'mongoc',
configsvr: true,
members: [
{_id: 0, host: 'db1:27018'},
{_id: 1, host: 'db2:27018'},
{_id: 2, host: 'db3:27018'}
]};
mongoc > rs.initiate(config)
configsvr: true を指定しているのがミソ
私はこれを忘れて小一時間ハマってました
ルータ(mongos)
基本手順は同じ
ただプロセスの実行ファイル名がmongodではなくmongosになったりmongos自体は実データを持たないプロセスなのでstorageの設定が不要、代わりにconfigDBで設定を持つレプリカセットを指定するという設定ファイルの違いがある
# mongos.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /data/log/mongos.log
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/mongos.pid # location of pidfile
# network interfaces
net:
port: 27017
#security:
#operationProfiling:
replication:
localPingThresholdMs: 15
sharding:
autoSplit: true
configDB: mongoc/db1:27018,db2:27018,db3:27018
## Enterprise-Only Options
#auditLog:
#snmp:
[Unit]
Description=High-performance, schema-free document-oriented database
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=--quiet -f /etc/mongos.conf"
ExecStart=/usr/bin/mongos $OPTIONS
PIDFile=/var/run/mongodb/mongos.pid
[Install]
WantedBy=multi-user.target
そして起動
systemctl daemon-reload
systemctl start mongos.service
エラーがなければこれで構成までは終わり
データを実際にシャーディング環境に載せるには
どっかの端末でmongosに接続する
今回の設定例ならシェルから
mongo
だけでつながるはず
プロンプトが
mongos>
になってれば正解
データベースをシャーディング環境に教える
mongos> sh.enableSharding('dbname')
その上でコレクションを指定してシャーディングさせる
どのシャードに格納するかを決定させるキーを指定すること
キーは予めインデックスを作っておいてください
mongos> sh.shardCollection('collection-name', { someIndex : 1 })
自動起動にも対応するなら
systemctl enable shard1.service
systemctl enable shard2.service
systemctl enable shard3.service
systemctl enable mongoc.service
systemctl enable mongos.service