中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

AWS上にハイパフォーマンスMongoDBを構築する方法

AWSインスタンスの選定

AWSインスタンスタイプ一覧

以下のインスタンスボリュームが付随しているプロダクトラインが候補になる。
個人的にはi2.xxx が好みである。

r3.xxx
メモリ最適化インスタンス
i2.xxx
SSD容量最適化インスタンス

ただし、インスタンスボリュームはスナップショットが取れず、揮発性なので取り回しが悪い。
Provisioned IOPS (SSD) ボリュームも検討候補になるが、高くつく事になるのでお金持ちの人用。。

バックアップ戦略

流石にバックアップを全く取らずに運用する事は出来ないので
以下様にレプリカセット構成を組み、バックアップを取る。

最後のノードはバックアップ専用なので、SSD以外は非力出よい。
ただしあまり小さいインスタンスを選択するとネットワーク容量が足りなくなるのでそこを考慮して選定する。

構成例

  • i2.4xlarge
  • i2.4xlarge
  • r3.large + 2400GiB EBS Magnet

もちろん負荷に依るが、この様な構成でも成立する。

AWS 周りの必要知識

//docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/i2-instances.html">i2インスタンス:基本使用ボリュームが大きいほどIOPSが高くなる

SSDオーバープロビジョニングの為に、10%ほど未使用領域を残す。激しく使うならi2.2xlarge以上。そうじゃないとネットワークが負ける。

//docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/InstanceStorage.html#InstanceStoreTrimSupport">TRIMサポート:i2 と r3 のインスタンスボリュームは TRIM がサポートされてる。
//docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/storage_expand_partition.html">パーティションファイルシステム設定関連:

手順

1. 普通に AWS console から作る場合


OS領域はマグネットで十分。インスタンスストアを全部追加すること。

2. デバイスを確認
# lsblk
NAME    MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
xvda    202:0    0    40G  0 disk
└─xvda1 202:1    0    40G  0 part /
xvdb    202:16   0 745.2G  0 disk

`xvdb` がインスタンスボリューム

3a. インスタンスボリュームが1つの場合はオーバープロビジョニング用の未使用領域を10%確保

インスタンスボリュームのサイズは800GiB単位で、インスタンスの大きさによって複数のインスタンスボリュームが付随する。
1つだった場合はそのまま使えば良いがSSDの性能を生かす為にオーバープロビジョニングの設定をする。

# gdisk /dev/xvdb

* パーティション(/dev/xvdb1)作成
Command : n
Partition number : 1
FirstSector: 2048
LastSector: XXXX ※ 最後のセクタから10%程余らせた部分を指定する
GUID: 8300

* 名前変更
Command : c
Enter name: Linux

* GUID生成
Command : x
Expert command : g
unique GUID: R

* 確認
Expert command: p
Disk /dev/xvdb: 1562822320 sectors, 745.2 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 4E2273AF-9E75-401A-8D3E-365A4D9674AC
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 1562822286
Partitions will be aligned on 2048-sector boundaries
Total free space is 156284525 sectors (74.5 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048      1406539775   670.7 GiB   8300  Linux

* 反映
Command : w
3b. インスタンスボリュームは2つの場合はRAID0を設定する

本来は各SSDにオーバープロビジョニングを指定した方が良いと思うが、そもそも大容量のストレージを常に使い切りそうな使い方自体がマズいので、運用上、常にある程度の未使用領域が残っている状態が保たれるはず。
そうなると、ある程度TRIMだけで対処できるのではないか?という想像の元にこうしている。
※ 誰か詳しい人が居たら教えてください

`mdadm` が無ければ apt-get install mdadm

インスタンスボリュームが4個の場合

# mdadm --create /dev/md0 --level=0 --raid-devices=4 /dev/xvdb /dev/xvdc /dev/xvdd /dev/xvde

以降、/dev/xvdb1 は /dev/md0 に読み替えてください。

4. ファイルシステムXFSを作る

`mkfs.xfs` が無ければ `apt-get install xfsprogs`

# mkfs.xfs -K /dev/xvdb1
5. マウント

TRIMを有効にする為にdiscardを指定する

# mkdir -p /data
# mount -o discard /dev/xvdb1 /data
== /etc/fstab ==

/dev/xvdb1 /data auto defaults,nobootwait,discard 0 2

# raidしている場合は `blkid /dev/md0`で取得できるuuidを指定する
UUID="**uuid**" /data auto defaults,nobootwait,discard 0 2
6. TRIM が効いてるか確認
# fstrim -v /data/
/data/: 3199094800384 bytes were trimmed
7. ここで一回リブートする
8. MongoDBディレクトリを作る
# mkdir /usr/local/mongodb
# mkdir -p /data/mongo
# ln -sfT /data/mongo /usr/local/mongodb/data
9. limits のnofileを多めに変更

https://docs.mongodb.org/manual/reference/ulimit/

後は普通にMongoDBを構築してください。
リンク先の設定がそのまま使えるはずです。

あまり頻発するような問題ではないようだ

http://d.hatena.ne.jp/hiroppon/20151216/1450251504
以前、MongoDB3.0系のバックアップを取り上げた。

色々検証したが、データファイル自体が破壊されるような事は起きなかった。
中のデータがある程度おかしいのかもしれないし、極稀にファイル破壊が起きるのかもしれないが
あまり大きな問題では無い様な気がする。

バックアップができない!?

ご存知の様にMongoDBのバックアップは

  1. fsyncLock
  2. Snapshot
  3. fsyncUnlock

の流れなのだが、、
最近、MongoDB3.2 系のドキュメントにこんな事が書かれていた

Compatibility with WiredTiger
Changed in version 3.2: Starting in MongoDB 3.2, db.fsyncLock() can ensure that the data files do not change for MongoDB instances using either the MMAPv1 or the WiredTiger storage engine, thus providing consistency for the purposes of creating backups.

In previous MongoDB version, db.fsyncLock() cannot guarantee a consistent set of files for low-level backups (e.g. via file copy cp, scp, tar) for WiredTiger.

まじか・・・ありえん!!
3.0 系に移行したばっかなのに、3.2系にまた移れってのか!?
データのコンシステンシーが多少失われてもまあ許容するが、データファイルが破壊されると厄介だ。
検証中だが、まだ問題は発生してない。。
うーむ。。。

MongoDB3.0.xの設定ファイルテンプレ

Advent Calendar にも投稿した内容ですが、MongoDB3系の設定周り。
僕はこんな感じで運用してますよ。という位の内容。

/usr/local/mongodb/ 以下に構築する場合の設定周り

1. ディレクトリ構成

バイナリをDLして適当に配置してください。

# mkdir -p /usr/local/mongodb/conf
# mkdir -p /usr/local/mongodb/logs
# mkdir -p /usr/local/mongodb/tmp
# ln -s <path to data path> /usr/local/mongodb/data
# ln -s <path to bin path> /usr/local/mongodb/bin

2. Keyfileを作る

MongoDB3系からセキュリティ周りが厳しくなり、replica-setへJOINさせる際にkeyfileによる認証が必要になりました。
StandAloneの場合は不要です。

openssl rand -base64 741 > /usr/local/mongodb/conf/mongod.key

設定ファイルテンプレ

しっかり設定しなければならないのは以下の2点くらい

storage.wiredTiger.engineConfig.cacheSizeGB: 100

インデックス構築や、cursor処理、メモリリーク(orz...)でも消費されるので
現状ではメインメモリの80% 程度に調整しておいた方が良さそうです。

replication.oplogSizeMB: 102400

これは用途によって適当に。。

processManagement:
  fork: true
  pidFilePath: /usr/local/mongodb/logs/mongod.pid

net:
  port: 27017
  maxIncomingConnections: 1000000
  unixDomainSocket:
    enabled: true
    pathPrefix: /usr/local/mongodb/tmp/
  http:
    enabled: false
    JSONPEnabled: false
    RESTInterfaceEnabled: false

security:
  authorization: enabled
  javascriptEnabled: true
  keyFile: /usr/local/mongodb/conf/mongod.key

operationProfiling:
  slowOpThresholdMs: 1000
  mode: slowOp

storage:
  engine: wiredTiger
  dbPath: /usr/local/mongodb/data
  directoryPerDB: true
  indexBuildRetry: true
  syncPeriodSecs: 60
  wiredTiger:
    engineConfig:
      cacheSizeGB: 100
      statisticsLogDelaySecs: 0
      journalCompressor: snappy
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: snappy
    indexConfig:
      prefixCompression: true
  journal:
    enabled: true

replication:
  oplogSizeMB: 102400
  replSetName: MyRS
  secondaryIndexPrefetch: all

MongoDB3系(WiredTiger)の現状

ご無沙汰してます。

最近全然更新出来てない訳ですが、MongoDBに愛想が尽きて、離れていた訳ではありません。
むしろガッツリ嵌ってます。。

最近は MongoDB3 系 WiredTiger を使いながら頑張っている訳ですが・・・
キリの良い所で書こうと思っていたのに、メドが立たないので近況だけでも書いておこうかと思った次第。。

で、、mongo3... コイツすぐ落ちる!!

まあ、普通にメモリーリークですが、、ちょっと目を離すと

Tasks: 169 total,   1 running, 168 sleeping,   0 stopped,   0 zombie
%Cpu(s): 12.4 us,  0.7 sy,  0.0 ni, 86.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  62916396 total, 62567524 used,   348872 free,    13332 buffers
KiB Swap:        0 total,        0 used,        0 free.    60212 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
16865 zenclerk  20   0 60.906g 0.058t   2744 S   0.0 98.3  12323:54 mongod
  859 syslog    20   0  322440   6900    216 S   0.0  0.0   0:02.80 rsyslogd

おい!舐めんな!!!
60GB使い切るか..


で、、最近 3.0.7が出ました。release note

なかでもこの2つは注目です

//jira.mongodb.org/browse/SERVER-20159">SERVER-20159 Out of memory on index build during initial sync even with low cacheSize parameter: そう。index張るとメモリー使い切って死ぬ・・・(メモリー足りてもリークしてたっぽい)
//jira.mongodb.org/browse/SERVER-20091">SERVER-20091 Poor query throughput and erratic behavior at high connection counts under WiredTiger: コネクションが多いとクエリーが重くなる・・・

早速試してますが、まあ改善した感じがします。
そろそろマトモになって来た感がありますね。
本番に使い始めてもよいかも〜


ただ、この大物が控えているのでまだ安心出来ません。。

//jira.mongodb.org/browse/SERVER-20306">SERVER-20306 75% excess memory usage under WiredTiger during stress test: 多分、僕の環境で起きてるのはコレなんだよなぁ・・

でも、逆にあとコレだけ解決してくれれば、いい感じになるはず!

MongoDB 3.0 リリースノート斜め読み

遂にMongoDB 3.0 が正式リリースされました!!
例によってリリースノートを斜め読みします。
http://docs.mongodb.org/master/release-notes/3.0/


が、、最初に一言で纏めると、まあ、、

目玉機能はロックレベルの話だけですよー



でわ。。

Pluggable Storage Engine AP

以下の2つからストレージエンジンを選べる。

MMAPv1
これまでのストレージエンジン。デフォルト
WiredTiger
3.0から追加されたストレージエンジン
WiredTiger

MongoDBの全ての機能をサポートしている。

MMAPv1とフォーマットが違うので既存のアップデートの場合、移行する際に色々必要。

ドライバも最新に上げないとダメ。

ドキュメントレベルロックが可能!!

touchコマンドはサポートしてない

MMAPv1 Improvements

コレクションレベルロック!!

領域確保のロジックが変更された

  • 大きなファイルの扱いが賢くなった
  • paddingFactorが廃止された。やった!

元々paddingFactorは賢い実装では無い。
稀に起きるかもしれないgrowing documentの為に
大半のそれ以外の処理に負がある方法を取るなんて馬鹿げた話だ。

ReplicaSet

ノード数が最大50になった。割とどうでも良い。

ステップダウンの挙動が変わった

  • stepdown の前にmap-reduce, index build などの長時間処理を殺す
  • (stepdown直前に入ったデータが)ロールバックされるのを避けるため次のPRIMARY候補のSECONDARYが追いつくまで待つ。

レプリカセットにJOIN時の同期が早くなった

writeConcernのmajority はvoting node のmajorityになった。細かい。。が、なるほど。

コンフィグのバリデーションが厳しくなった

セカンダリのコレクションには必ず_id インデックスが作られる。(バグフィックスに近い)

Sharded Clusters

セキュリティー周り。細々改善。

Improvements

クエリープラン改善とexplain改善

ログ周り改善

mongo_tools 周り色々改善。
うれしいけど細かい!!

この辺り使い倒してる人がどれだけいるんだろうか?
ウチあの辺この辺とか位?w

dropIndex, dropCollection, dropDatabaseしたときにバックグラウンドで動いているcreateIndexは中止されるようになった。

shard key を含むインデックスはcover query になり得る。

geo系クエリー強化

aggregateに$dateToString 追加

$eq 追加?なんの意味があるの?

MongoDB Enterprise Features

パス

その他

2.6系からしかアップグレード出来ない。

3.0からは 2.6.5 までしかダウングレード出来ない。

2.6.8未満のmongo shell から3.0に繋げると色々問題。