whoami
商品開発部の飯伏です。
現場クラウドConneというサービスの開発マネージャー、現場サポートのサービス基盤インフラチーム(チームだけど独り、絶賛求人中)をやっています。
最近のお気に入りのディストリビューションはarchlinuxです。
なぜ移行するのか?
AppとDBを同一インスタンスで運用していました。
サーバーリソースの取り合いとなり、DBのせいで重いのか、Appのせいで滞っているかの判別だけで一苦労。
DBが重くなると関係の無いAppの処理でも巻き添えを食うなどの問題も。
単純に別インスタンスに分割する、も考えましたが。
地味にバックアップに時間とサーバーリソースを食われて夜間バッチ処理の時間が削られ。
いざというときの復元もナカナカの人的コストがかかります。
かといってスケールアップで対応してもAppも分散させて方がいい機能もあったり。
というわけで、マネージドサービスのDocumentDBへの移行を決断しました。
移行手段の検討
移行手段の候補は大きく分けて3つ。
- mongodump & mongorestore
- レプリカ構成を作ってデータ同期しつつ入れ替え
- AWS Database Digration Service を活用
mongodump & mongorestore は最初に検討しましたが。
結構時間かかってしまうしこのためだけにスケールアップするのもな、と思い。
パイプで流すとコケたら最初からやり直し。
かといってEFS等にダンプデータを一時置いても更に時間がかかるだけ。
なので今回は避けることに。
レプリカ構成を作って移行はDocumentDBをスレーブとして参加させられないのでボツ。
AWS Database Migration Service(以下AWS DMS)は試してみた所。
DMSインスタンスのサイズに応じてスピードが変わるようで。
移行時停止が必要なものの、富豪インスタンスで移行すればなんとかなりそう。
そこで今回はAWS DMSで移行することに。
実際の移行
公式の Migration from MongoDB to Amazon DocumentDB に従って移行すればよい。
試行時に気づいたとおり、書き込みがボトルネックに。
そのため、移行時に限りインスタンスサイズをr4.2xlargeにまで増強。
300GBの移行が40min弱で完了。
この時、GridFSのchunks移行時間の大半を占める。
容量の大半はGridFSなのだけれど、移行時間も9割方chunksの移行。
結果として思ったのだけれど。
GridFSに大容量ファイルを大量に置くのは効率あまり良くない??
運用してみて
当初の見込み通り、アプリとDBを分離出来たことで運用コストは低減。
バックアップなど手間も省け、ログも十二分に取れるので運用に支障なし。
一方でいくつか出くわした問題は、順次対処。
$in検索の劣化
一方で大きなID配列での$in検索がmonbodbと比べて2倍ほど遅くなっていた。
とはいえID配列のサイズが100行超えるくらいから劣化してくれるので。
どちらかといえばアプリの作り的な問題。
バッチ処理だったのでIDを分割してループさせることで回避した。
$elemMatch のインデックスが効かない件
移行前検証で見落としていた$elemMatchのインデックスが効かないのは困った。
こちらはアプリの該当部分でidマッチするようフィルターを書き換えて対処。
{“users”: {“$elemMatch”: {“id”: ObjectId(“xxx”), “foo”: “bar”}}}
これではインデックスが効かないので。
{
“users.id”: ObjectId(“xxx”),
“users”: {“$elemMatch”: {“id”: ObjectId(“xxx”), “foo”: “bar”}}
}
インデックスを使うためだけにフィルターを冗長に書き換え。
Concurrent operations on the same resource
これはレアケースな気はするがupdateManyの時に Concurrent operations on the same resource というエラーが発生していた。
今のところはアプリの処理を書き換えて同時更新の確率を下げて止血。
DocumentDBのバグが解消するまでに頻発するようなら、同時更新を起こさないようにバックグラウンドジョブとして書き換える予定。
まとめ
準備/検証にそれなりに時間をかけ、移行後のいくつかの問題も片付け。
容量は自動スケールだし、スケールアップ、スケールアウトもaws-cliを叩くだけ。
労力に見合ったメリットは享受できている、気がする。