サイバーエージェントを支える技術者たち

第21回 MongoDB最前線!実戦投入の光と影と開発ノウハウ

この記事を読むのに必要な時間:およそ 3 分

高可用性を実現するレプリカセットのしくみ

データストアを選定する際,ポイントの1つとして可用性が挙げられます。データストアとして利用しているサーバにハードウェア障害が生じても,別のサーバに切り替えて処理を継続するなどといったしくみがあれば,運用面での負担を大きく軽減することが可能でしょう。

可用性を実現するためにMongoDBで提供されているのが「レプリカセット」と呼ばれているしくみです。これは1台のプライマリと複数台のセカンダリを利用し,それぞれの間で非同期でのレプリケーションを行い,プライマリが「落ちた」場合にはフェイルオーバーを行うというもの。これによって高い可用性を実現することが可能になります。

ただ,レプリカセットの目的はあくまでも高可用性を実現することです。レプリケーションによって複数台のサーバを同期して負荷分散を行い,パフォーマンスを向上させるためのしくみではありません。セカンダリからデータを読み出すしくみは用意されていますが,基本的にはフロントに立っているのはプライマリのみで,3台のサーバを用意しても性能は1台分ということになります。そのため,スケールアウトさせたい場合はシャーディングを組み合わせて使うというのがMongoDBの基本的なスタンスです。

こうしたしくみのため,ハードウェアの利用効率はけっして高くないと名村氏は指摘します。

「たとえば5台分のパフォーマンスが必要な場合,レプリカセットを5セット追加するという話になります。そのレプリカセットをプライマリ1台,セカンダリ2台で構成している場合,5×3=15台のマシンが必要となり,物理サーバで構成している場合は相当数のサーバが必要になります。ちなみに現状ピグライフでは50台くらいを利用していますが,それでも足りないのであと30台くらい追加しようとしています」⁠名村氏)

このようにハードウェアの利用効率はよくありませんが,⁠足せばとりあえず(シャーディングの機能によって)パフォーマンスが確保できるので,お金さえかければ何とかなるという意味では楽といえば楽ですね」⁠名村氏)とのこと。

さらに「MongoDBはスキーマレスであるため,データのヘッダ情報を全ドキュメントで持っているので,ディスク領域という意味でもあまり効率は良くありません」と指摘するのは津田氏です。圧縮するしくみがなく,個々のデータはバイナリでもカラム名などはテキストで保持していることも響いているようです。特にシャーディングのノード数を絞りつつ,大規模なデータを保存したいといったケースでは注意が必要でしょう。

MongoDBを利用したアプリケーション開発での注意点

さて,MongoDBは比較的新しいデータストアであり,開発時において注意することも少なくありません。たとえばNode.jsを使ってピグライフを開発した名村氏は,Node.jsからMongoDBに接続するドライバでトラブルがあったと話します。

「実はMongoDBのNode.js用のドライバは公式としては存在していません。ただ,オープンソースのドライバがいくつかあり,そのうちの1つをピグライフでは使っているのですが,当初はドキュメントが壊れたり,あるいはプロパティの数によって2つのドキュメントが保存されてしまったりと,けっこうひどいバグがたくさんありました。最近はだいぶ改善されていますが,まだこちらで作ったパッチを適用しないとあるタイミングでフリーズしてしまうなど,現状では安心して使える状況とは言い難いですね」⁠名村氏)

さらにもう1つ,JavaScriptでMongoDBを利用する際に注意すべき点として名村氏が挙げるのはJSONとBSON(Binary JSON)の相性です。MongoDBではドキュメントをBSONと呼ばれる形式で保存しますが,このBSONとJSONを相互変換する際,格納されているデータの型によって問題が生じる場合があるとのこと。具体的にはJavaScriptではサポートしていない64ビットの整数をBSONからJSONに変換しようとしたとき,文字列になったりdouble型になったりといったことが起きると指摘します。ただ,こうした相互変換の問題はドライバが原因ではないかとのことで,今後ドライバの改善が進めば解消される可能性はありますが,しばらくの間は注意が必要のようです。

ドキュメントのサイズにも注意が必要と説明するのは津田氏です。次々とデータをドキュメントに格納していると,ドキュメントが肥大化してしまい,ドキュメントサイズの制限を超えてしまってエラーが発生したり,あるいはパフォーマンスが低下したりすると言います。

「最初,あまり深く考えずにとりあえず動くものを作ろうと開発していたときだったのですが,ドキュメントサイズの制限を軽くオーバーしてエラーが発生したことがありました。MongoDBのバージョンアップによってドキュメントサイズの制限は多少緩和されていますが,ドキュメントサイズが大きくなると更新が遅くなるなどの弊害があり,またネットワークにも負担がかかるため,ドキュメントが肥大化しないように設計の段階から注意すべきだと思います」⁠津田氏)

画像

パフォーマンス低下を防ぐコツ

最後にパフォーマンスを向上させるためのコツについて伺ってみました。特にパラメータ調整を施さずともそこそこのパフォーマンスを発揮するMongoDBですが,性能の低下を抑えるためにはどういった点に注意すべきなのでしょうか。

開発時における注意点として,名村氏は「データを更新する際,ドキュメントを丸ごと取ってきて中身を書き換え,ドキュメントごと保存するような処理はやめたほうがよい」と話します。その理由となっているのが「oplog」の存在です。

oplogとはデータ更新に対するオペレーションを記録した一種のデータベースであり,MongoDBのレプリカセットでは,このoplogを利用してレプリケーションを行っています。当然ながらデータ更新を行うと必ずoplogのための処理も発生するため,大きなデータの更新を行えばそれだけ負荷も高まってしまうというわけです。

さらにシャーディング時にどのキーを使って分散するかの調整も重要とのこと。できる限り分散して処理ができるようにキーを設定するのが基本ですが,どういった処理が多いのかによって考え方は変わると津田氏は説明します。

「たとえば前方一致で最初の10件だけを取得するといったクエリを投げる場合,その10件が分散しているとすべてのサーバに対してクエリを投げるという処理が発生しますが,1つのサーバに集約するようにキーを設定しておけば高速に結果を得られます。一方,何らかの値を連続して書き込むというケースでは,複数のサーバに分散したほうが短時間で処理が終了します。このため,使い方に合わせてキーを設定することが重要です」⁠津田氏)

早い時期からMongoDBを導入してきたサイバーエージェントならではの導入と開発のためのノウハウを紹介しましたが,参考になったでしょうか。次回は運用面を中心に,さらにMongoDBの活用術に迫ります。

サイバーエージェント公式エンジニアブログ
URL:http://ameblo.jp/principia-ca
エンジニアの生の声を週替わりでお届け中!

著者プロフィール

川添貴生(かわぞえたかお)

株式会社インサイトイメージ代表取締役。企業サイトの構築及び運用支援のほか、エンタープライズ領域を中心に執筆活動を展開している。

メール:mail@insightimage.jp