この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、菊池です。クラスメソッドにJOINして1ヶ月が経ちました。
先日のブログで、AWSクイックスタート:MongoDB on the AWS Cloudを試してみたという記事を書きました。MongoDBクラスタを簡単に構築できるCloudFormationテンプレートでしたが、公開から若干時間が経っているため、以下のような改善点があると記載しました。
- MongoDBのストレージエンジンをWiredTigerにする
- MongoDB 3.0 からストレージエンジンとしてWiredTigerが使用可能になっていますが、デフォルトではMMAPv1となります。WiredTigerを使うことで、データ圧縮や、書き込み性能の大幅向上などのメリットがあります。
そこで今回は、テンプレートから構築したMongoDBクラスタのストレージエンジンをWiredTigerにアップグレードしてみたいと思います。
WiredTiger StorgeEngine とは
MongoDB Manual : WiredTiger Storage Engine
MongoDB Ver 3.0から採用されたストレージエンジンで、それまでのMMAPv1に比べて以下のような優位性があります。
データ圧縮
MongoDBはJOSNドキュメントを保管しますので、各項目のkey:valueがそのまま記載されます。そのため、RDBに比べてデータの物理的なサイズが肥大しがちです。データ圧縮が可能になったことで、データボリュームの肥大化を抑えることができます。
ロックの改善
MongoDB Ver 2.6まではデータ更新時のロックがデータベースレベルロックでした。そのため、書き込みが多い用途ではロック待ちが大きくなっていました。Ver 3.0以降で採用されたWiredTigerを使うことで、ドキュメントレベルロック(RDBの行ロックに相当)になりますので、ロック待ち時間が劇的に削減され、書き込み性能が大幅に向上されました。
なお、MongoDB Ver 3.2系ではWiredTigerがデフォルトになっています。
構成
前回のエントリで構築した環境をそのまま利用します。
作業対象はClusterに参加しているPrimary/Secondaryの3ノードです。
作業手順
大まかには以下の通りです。
- Secondary00を停止し、ストレージエンジンを変更
- Secondary00を起動しデータ同期を実施
- Secondary01に対し上記1, 2 を実施
- Primary00に対し上記1, 2 を実施
レプリカセットのクラスタでは異なるストレージエンジンを混在可能ですので、上記のようにローリングアップデートを実施することで、オンラインのまま作業が可能です。
Secondaryのストレージエンジン変更
まずはPrimaryでレプリカセットの状態を確認します。
s0-rs0:PRIMARY> rs.status()
{
"set" : "s0-rs0",
"date" : ISODate("2016-09-30T09:15:11.013Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "10.0.2.243:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 516,
"optime" : Timestamp(1475226404, 1),
"optimeDate" : ISODate("2016-09-30T09:06:44Z"),
"electionTime" : Timestamp(1475226407, 1),
"electionDate" : ISODate("2016-09-30T09:06:47Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "10.0.4.32:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 507,
"optime" : Timestamp(1475226404, 1),
"optimeDate" : ISODate("2016-09-30T09:06:44Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:15:10.730Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:15:10.742Z"),
"pingMs" : 2,
"configVersion" : 1
},
{
"_id" : 3,
"name" : "10.0.3.244:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 507,
"optime" : Timestamp(1475226404, 1),
"optimeDate" : ISODate("2016-09-30T09:06:44Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:15:10.228Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:15:10.237Z"),
"pingMs" : 0,
"configVersion" : 1
}
],
"ok" : 1
}
3台とも認識されています。Secodary00にログインし、mongod0のサービスを停止します。
$ sudo service mongod0 stop
Stopping mongod: [ OK ]
もう一度Primaryで状態を確認すると、
s0-rs0:PRIMARY> rs.status()
{
"set" : "s0-rs0",
"date" : ISODate("2016-09-30T09:17:21.357Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "10.0.2.243:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 646,
"optime" : Timestamp(1475226404, 1),
"optimeDate" : ISODate("2016-09-30T09:06:44Z"),
"electionTime" : Timestamp(1475226407, 1),
"electionDate" : ISODate("2016-09-30T09:06:47Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "10.0.4.32:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 637,
"optime" : Timestamp(1475226404, 1),
"optimeDate" : ISODate("2016-09-30T09:06:44Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:17:20.908Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:17:20.932Z"),
"pingMs" : 2,
"configVersion" : 1
},
{
"_id" : 3,
"name" : "10.0.3.244:27018",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : Timestamp(0, 0),
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:17:20.313Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:16:30.285Z"),
"pingMs" : 0,
"lastHeartbeatMessage" : "Failed attempt to connect to 10.0.3.244:27018; couldn't connect to server 10.0.3.244:27018 (10.0.3.244), connection attempt failed",
"configVersion" : -1
}
],
"ok" : 1
}
s0-rs0:PRIMARY>
Secondayが1ノード通信できない状態となっています。
ストレージエンジン変更のため、/etc/mongod0.confを編集します。
変更前:
$ cat /etc/mongod0.conf
net:
port: 27018
systemLog:
destination: file
logAppend: true
path: /log/mongod0.log
storage:
dbPath: /data/s0-rs0
journal:
enabled: true
processManagement:
fork: true
pidFilePath: /var/run/mongod/mongod0.pid
replication:
replSetName: s0-rs0
変更後:
$ cat /etc/mongod0.conf
net:
port: 27018
systemLog:
destination: file
logAppend: true
path: /log/mongod0.log
storage:
dbPath: /data/s0-rs0
journal:
enabled: true
engine: "wiredTiger"
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
statisticsLogDelaySecs: 0
collectionConfig:
blockCompressor: "snappy"
processManagement:
fork: true
pidFilePath: /var/run/mongod/mongod0.pid
replication:
replSetName: s0-rs0
blockCompressor: "snappy"
は圧縮の方式で、圧縮率と不可のバランスをとった形式です。
そして、dbPath: /data/s0-rs0
以下にあるデータを全て削除します。
$ sudo rm -rf /data/s0-rs0/*
なかなか抵抗があるコマンドですが、データを全て削除し、再度起動することでレプリカセットの他のノードからデータを再同期します。この再同期の際に、新たに設定したWiredTigerの形式でデータが再構成されます。
そして、mongod0を起動します。
$ sudo service mongod0 start
Starting mongod: [ OK ]
Primaryで状態を確認すると、
s0-rs0:PRIMARY> rs.status()
{
"set" : "s0-rs0",
"date" : ISODate("2016-09-30T09:28:33.664Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "10.0.2.243:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1318,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"electionTime" : Timestamp(1475226407, 1),
"electionDate" : ISODate("2016-09-30T09:06:47Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "10.0.4.32:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1309,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:28:31.896Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:28:31.917Z"),
"pingMs" : 2,
"syncingTo" : "10.0.2.243:27018",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "10.0.3.244:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 128,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:28:33.054Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:28:33.066Z"),
"pingMs" : 0,
"syncingTo" : "10.0.2.243:27018",
"configVersion" : 1
}
],
"ok" : 1
}
s0-rs0:PRIMARY>
正しく認識されています。
同様の手順をSecodary01でも実施します。
Primaryのストレージエンジン変更
続いてPrimaryです。
Secondaryと同様、Primaryノードのmongod0プロセスを停止します。
$ sudo service mongod0 stop
Stopping mongod: [ OK ]
起動しているSecondaryにログインし、状態を確認します。
s0-rs0:SECONDARY> rs.status()
{
"set" : "s0-rs0",
"date" : ISODate("2016-09-30T09:32:44.057Z"),
"myState" : 2,
"members" : [
{
"_id" : 1,
"name" : "10.0.2.243:27018",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : Timestamp(0, 0),
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:32:43.217Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:31:25.040Z"),
"pingMs" : 0,
"lastHeartbeatMessage" : "Failed attempt to connect to 10.0.2.243:27018; couldn't connect to server 10.0.2.243:27018 (10.0.2.243), connection attempt failed",
"configVersion" : -1
},
{
"_id" : 2,
"name" : "10.0.4.32:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 379,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:32:43.458Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:32:42.330Z"),
"pingMs" : 2,
"electionTime" : Timestamp(1475227888, 1),
"electionDate" : ISODate("2016-09-30T09:31:28Z"),
"configVersion" : 1
},
{
"_id" : 3,
"name" : "10.0.3.244:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 380,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"configVersion" : 1,
"self" : true
}
],
"ok" : 1
}
s0-rs0:SECONDARY>
Primaryだったノードが接続不能になり、Secondaryの1台がPrimaryに昇格しています。このようにMongoDBのレプリカセットではPrimaryが停止すれば自動でいずれかのSecondaryが昇格します。
あとはこれまでのSecondaryと同様です。設定変更後、起動します。再度状態を確認すると、
s0-rs0:SECONDARY> rs.status()
{
"set" : "s0-rs0",
"date" : ISODate("2016-09-30T09:35:02.123Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "10.0.2.243:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 9,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"electionTime" : Timestamp(1475228097, 1),
"electionDate" : ISODate("2016-09-30T09:34:57Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "10.0.4.32:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 8,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:35:01.759Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:35:01.126Z"),
"pingMs" : 2,
"configVersion" : 1
},
{
"_id" : 3,
"name" : "10.0.3.244:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 8,
"optime" : Timestamp(1475227704, 1),
"optimeDate" : ISODate("2016-09-30T09:28:24Z"),
"lastHeartbeat" : ISODate("2016-09-30T09:35:01.749Z"),
"lastHeartbeatRecv" : ISODate("2016-09-30T09:35:01.476Z"),
"pingMs" : 0,
"configVersion" : 1
}
],
"ok" : 1
}
s0-rs0:PRIMARY>
Primaryが元に戻っています。レプリカセット設定によりプライオリティが高いノードが復帰すれば、自動でPrimaryに昇格します。
s0-rs0:PRIMARY> rs.conf()
{
"_id" : "s0-rs0",
"version" : 1,
"members" : [
{
"_id" : 1,
"host" : "10.0.2.243:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 10,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 2,
"host" : "10.0.4.32:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 5,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 3,
"host" : "10.0.3.244:27018",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 5,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatTimeoutSecs" : 10,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
}
}
}
s0-rs0:PRIMARY>
以上でストレージエンジンの変更は完了です。
変更前後のデータパスの構成を確認してみます。
変更前:
$ ls -l /data/s0-rs0/
合計 21125172
lrwxrwxrwx 1 mongod mongod 15 9月 30 09:06 journal -> /journal/s0-rs0
-rw------- 1 mongod mongod 67108864 9月 30 09:34 local.0
-rw------- 1 mongod mongod 2146435072 9月 30 09:28 local.1
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.10
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.2
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.3
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.4
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.5
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.6
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.7
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.8
-rw------- 1 mongod mongod 2146435072 9月 30 09:06 local.9
-rw------- 1 mongod mongod 16777216 9月 30 09:34 local.ns
-rw-r--r-- 1 mongod mongod 6 9月 30 09:34 mongod.lock
-rw-r--r-- 1 mongod mongod 69 9月 30 09:06 storage.bson
-rw------- 1 mongod mongod 67108864 9月 30 09:28 testDB.0
-rw------- 1 mongod mongod 16777216 9月 30 09:28 testDB.ns
変更後:
ls -l /data/s0-rs0/
合計 176
-rw-r--r-- 1 mongod mongod 46 9月 30 09:26 WiredTiger
-rw-r--r-- 1 mongod mongod 533 9月 30 09:26 WiredTiger.basecfg
-rw-r--r-- 1 mongod mongod 21 9月 30 09:26 WiredTiger.lock
-rw-r--r-- 1 mongod mongod 875 9月 30 09:29 WiredTiger.turtle
-rw-r--r-- 1 mongod mongod 61440 9月 30 09:29 WiredTiger.wt
-rw-r--r-- 1 mongod mongod 36864 9月 30 09:29 _mdb_catalog.wt
drwxr-xr-x 2 mongod mongod 4096 9月 30 09:28 collection
drwxr-xr-x 2 mongod mongod 4096 9月 30 09:28 index
drwxr-xr-x 2 mongod mongod 4096 9月 30 09:26 journal
-rw-r--r-- 1 mongod mongod 6 9月 30 09:26 mongod.lock
-rw-r--r-- 1 mongod mongod 36864 9月 30 09:29 sizeStorer.wt
-rw-r--r-- 1 mongod mongod 95 9月 30 09:26 storage.bson
変更前後で構造は大きく変わっています。WiredTigerでは、IndexやDB単位でディレクトリを分けることも可能です。
まとめ
テンプレートから構築したクラスタのストレージエンジン変更手順を紹介しました。
今、MongoDBを使うのであればWiredTigerを利用しない理由はありませんので、Ver 3.0以降を使うのであれば既存のデータも可能な限り移行していくことをおすすめします。