MongoDBを使用する機能





1年ちょっと前に、私は狭いサークルで知られている1つのソーシャルネットワークの開発に参加するように頼まれました(常に良い面ではありません)。 当時、私はすでにHaxe言語のファンだったので、何を書くべきかについての質問はありませんでした。 しかし、データベースでは彼らが登場しました。 MS SQL ServerとMySQLの使用経験によれば、大量の情報に関しては、時々困難が生じることがあります(データベースの構造を変更することはほとんど不可能になり、高速クエリはすでに非常に遅くなります)。 同僚(すでにMongoの経験がある)と相談した後、この特定のDBMSを使用することにしました。 そして、今年中に表面化したこれらの機能について、以下に説明します。



作業安定性



数か月使用した後、興味深い問題が発生しました。 これは次のようなものでした。コレクションの1つに対してインデックスの作成を開始した後、インデックスが正しくないことがわかったため、 db.killOp()使用してプロセスを削除できました。 その後、インデックスは正式に表示されましたが、このコレクションで任意のインデックス( naturalを除く)を使用しようとすると、DBMSは内部エラーを返しました(一部のアサートはコードで機能しました)。 なぜなら コレクションには1億件近くのレコードが含まれていたため、そのリクエストは不可能になり、新しいコレクションにデータを転送する間、数日間サービスを停止する必要がありました。 また、古いコレクションはデータベースに残っています-通常の方法では削除できません。

その結果、1つのサービスに関連するすべてのコレクションがDBMSの個別のインスタンスに配置され、クリティカルな状況では停止および修正できるため、1つのサービスのみの可用性が犠牲になります。



予備コピー



情報のバックアップ方法の決定に多くの時間が費やされました。 最初に思いついた方法-レプリカのセットを作成する-は、障害発生時にデータベースの最後のコピーではなく、以前のコピーが必要な場合があるという意味で、少し不適切と思われました。 さらに、バックアップを削除するときは、本番環境に追加の負荷をかけないことをお勧めします。 その結果、マスタースレーブ構成を使用するようになりました。この構成では、通常の方法でスレーブが時々バックアップされます。

ヒント:証明書によるセキュリティ設定を回避するには、インスタンスのローカルマスターデータベースとスレーブデータベースにユーザー「repl」を作成します。



use local db.addUser("repl", "mypassword")
      
      







一意のインデックス



SQLの相対的なセキュリティに慣れていると、トラブルに巻き込まれる可能性があります。 そのような事件が発生しました。コレクションの1つについて、2つのフィールドに一意のインデックスを作成し始めました。1つは多数のレコードに存在せず、もう1つは定期的に繰り返されました。 ミスの結果、DBMSはコレクションからデータを削除し始めました。 これを実現するために、数秒後にdb.killOp()による削除プロセスを削除し、情報が後で復元されました。 しかし、彼らが言うように、堆積物は残った。 したがって、マニュアルに記載されているように、 dropDups:trueを注意して使用してください



カウンター



大量のデータで特定のフィルターに一致する要素の数をカウントする操作は、SQLと比較すると非常に長い時間がかかる場合があります。 問題は、Mongoがインデックスツリーにサブノードの数を格納しないことです。 その結果、クエリが完全にインデックスに該当する場合でも、DBMSはフィルターに適したすべてのレコードをバイパスするように強制されます(多くの場合、それらがあります)。 そのため、カウンタを個別に保存し、必要に応じて変更する準備をしてください。 または、指定された頻度でカウンターの値を再カウントするバックグラウンドサービスがあります。 状況に応じて、両方の方法を使用します(1つ目は写真のコメント数などの単純なケース、2つ目は複雑なもので、異なる条件のセットに該当するレコード数をコレクションに保存する必要がある場合)。



ログローテーション



ログファイルのサイズなどの「些細な」ことを忘れないでください。 結局のところ、デフォルトでは、Mongoはデータベースに関するすべての操作をそれに書き込みます。 したがって、実稼働システムでは、パーティション上のすべてのスペースをすぐに使用できます。 重要ではないインスタンス(バックアップ用のスレーブなど)では、完全に無効にする方が良いと思われます。 その他では、ローテーションを整理します。



安全性



特別な構成がなければ、Mongoがパスワードなしでインターネットをサーフィンすることが簡単にわかります。 初期設定後、管理者ユーザーを作成することを忘れないでください。



 use admin db.addUser("root", "mypassword")
      
      







さらに、このDBMSは、ネットワーク上の統計情報を含む httpページ( nohttpinterfaceオプションを参照)も表示できることに注意してください。



全文検索



一般に、それは動作します。 次のことだけを覚えておいてください。



  1. 言語(特にロシア語)は正しくサポートされていません-たとえば、Mongoは多くのヒューリスティックルールを使用してエンディングを検出しますが、例外リストまたはそのようなものは保存しないため、このような検索から特別なものを期待しないでください。
  2. 多くのエントリが検索クエリに該当する場合(一般的な単語を検索した場合)-それは悪いでしょう。 つまり、クエリは長時間(この場合は約30秒以上)実行され、仮定を導入せずに何らかの形でそれに影響を与えることは困難です(検索の前に制限を行います-データの一部を見つけられません-さて、大丈夫です)。

    したがって、Mongoで全文検索を使用しますが、それはすぐに使用できるからです。 質の高い検索が重要な場合は、スフィンクスのようなものを使用してください。




結論



一般に、ドキュメント指向モデルの水平方向の拡張性と柔軟性が欠点を上回るという選択に満足しました。

現在、私たちのソーシャルネットワークは数十台のサーバー上で動作していますが、チームが作成したサービスはサーバーコード( HaQuery Webフレームワークを使用してhaxeで記述され、 nekoでコンパイルされている)のために1台のマシンに完全に保持されていますが、 DBおよびMongoスレーブインスタンス用。

使用されるMongoDBのバージョンは2.4.5です。



プロジェクトでMongoDBを使用することを検討している場合は、この記事が正しい決定を下すのに役立つことを願っています。



All Articles