はじめに
同僚は、アプリケーションを開発するときに、情報の柔軟な保存(更新、検索など)の必要性に毎日直面しています。 私たちは皆知っているように、この範囲の問題を解決する製品のクラスはデータベースです。 しかし、私たちの理解には何がありますか? 多くの場合、「データベース」はMySQL、テーブル、およびSQLクエリに強く関連付けられています。 そして、それはある程度まで適しています。 実際、リレーショナルデータベースには多くの作業上の利点があります。データには強力な接続性があるため、データベースの整合性を制御する必要はありません。 シンプルなサブリクエストを使用して、各ブログ投稿のコメント数を選択できます。 JOINを使用すると、複雑な関連選択を行い、複数のエンティティに関するデータを一度に取得することは難しくありません。
スケーリング済み、スケーリング済み、ただしスケーリングなし
ただし、1台のサーバーではもう十分ではないことを突然認識し、データベースを複数の物理マシンに分散させたい場合、最初に提供されるのは、マスタースレーブレプリケーションです。 ただし、十分な数の変更があると、すぐにマスターはログの配布のみを行い、各ノードが1つのマスターサーバーを持ち、複数のスレーブサーバーを持つことができるように高度な設定に頼る必要があります。 このスキームは実装が非常に難しく、単一障害点が含まれています(つまり、1つのサーバーに障害が発生すると、そのすべての部下がすぐに恐竜に変わります)。 繰り返しますが、これらのトリックはすべて読み取りの数を増やすだけです。 また、1つのサーバーの容量がデータベースの状態を変更するのに十分でない場合、異なるサーバーに異なるテーブルを保存して負荷を分散する必要があります。 しかし、その後、つながりが失われます。 または、テーブルを複数の部分に分割して、特定の法律(IDなど)に従って異なる場所に保存する必要がありますが、これはチャームをJOIN墓に連れて行きます。 リレーショナルデータベースをさらに拡張しようとすればするほど、そのための利便性は高まります。 たとえば、master-masterを使用する場合、自動インクリメントで支払います。
MemcacheDBとRedisは私たちを救いますか?
同様のKey-Valueソリューションがかなり前から存在していました。 私の意見では、MemcacheDBは素晴らしい製品の良い名前を寄生するクラフトです。そこにあるデータは絶対に無関係であり、キーを知っている値に対してのみ操作を実行できます。 MemcacheDBのようなキーと値のデータベースでうまく動作できるツールキットを書くのに多くの時間を費やしましたが、単純な緊急のタスクは非常に曲がって解決されているので、あなたは無意識のうちにリレーショナルの方向に考えます。たとえば、時間の基本的な実装さえありませんオブジェクトライフ(TTL)、つまり 1か月以上前のセッションを取得および削除することはできません。 配信しません。
Redisの作者は、倒錯した空想をもう少し進めて、アトミックリストとキーのセットを作成しましたが、プログラマを簡単にするのに大きな進歩はありませんでした。
さらに、キーキャッシュを手動で維持する必要があります。 Memcachedに必要なキーを保存してそこから取り出します。これにより、同期に多くの問題が発生します。 同時に、操作のアトミック性はありません。オブジェクトの受信とキャッシュへの書き込みとの間に競合があり、CASはそのパフォーマンスを落胆させます。
Yandex.Marketタイプ別の商品カタログが必要な場合はどうすればよいですか?
価格、評価、カメラのズーム比、自転車のギア数などのパラメーターで検索するカタログを作成するとします。 MySQLのようなリレーショナルデータベースを使用するとしましょう。 私たちは何をすべきですか? 自転車のズーム比とギア数の両方が含まれる商品テーブルを作成する必要があります。たとえば、歯ブラシの毛の柔軟性の指標があります(この場合、テーブルのフィールド制限に達するか、速度が低下します)または利便性)、またはgood_id、key、valueのような記号を用意し、スケーリングについてst音を立てることなく、選択と検索のために怖いJOINを作成する必要があります。
Sphinxを設定することもできますし、もっと悪いこともできますが、ラップトップに釘を打ち込むように見えます。
関係のある女性は重度の出生障害を持っています。
MongoDBを話しますか?
MongoDBは、下痢オブジェクトドキュメントデータベースです。 イデオロギー的に、これは通常のリレーショナルデータベースとキーバリューストレージの一種の共生であり、私の意見では非常に成功しています。 一方では、オブジェクトの識別子を知って、オブジェクトに対して非常に高速な操作を行うことができ、他方では、複雑な相互作用のための強力なツールを提供します。
コレクションはオブジェクトの名前付きセットであり、1つのオブジェクトは1つのコレクションにのみ属します。
オブジェクトは、一意の識別子_idを含むプロパティのコレクションです。
プロパティは、名前とそれに対応するタイプと値の組み合わせです。
プロパティタイプ-文字列、整数、浮動小数点、配列、オブジェクト、バイナリ文字列、バイト、文字、日付、ブール、null。
フェッチ(カウント、グループ、MapReduce ...)、挿入、変更、および削除の操作がサポートされています。 オブジェクト間に接続はありません。オブジェクトはプロパティに他のオブジェクトのみを保存できます。 一意のインデックスと複合インデックスの両方がサポートされています。 ネストされたオブジェクトのプロパティにインデックスを重ねることができます。
レプリケーションがサポートされている(暗黙であっても)、フェールオーバーが実装されています。
MapReduceとシャーディングを実装しました。
オブジェクトはプロパティの任意のセットを持つことができるため、カタログの場合、商品コレクションを作成してそこにオブジェクトを配置するだけで十分です。 この場合、検索はインデックスによって実行されます。
MongoDBのシャープネスはinsert'ahで発音され、非常に速く発生します。 ところで、ネットワーク上のオブジェクトのストレージ形式と送信形式が同じであると便利です。そのため、オブジェクトを選択するには、インデックスでその位置を見つけ、特定の長さのファイルの一部をクライアントに返すだけです。ストレージエンジンを抽象化しません。
一意の識別子として、自動インクリメントフィールドではなく、クライアントで生成された12バイトの一意の番号が使用されます。 したがって、まず、レプリカの同期に問題はありません。 2つの異なるマシンに個別に挿入でき、競合は発生しません。 第二に、整数オーバーフローのでたらめはありません。まあ、データベースを再作成した後、検索エンジンは古いリンクを使用して新しい記事に対処しません。
MongoDB + Memcached? ボニーとクライドよりも良い!
Memcachedの速度でホットケーキを提供したいので、データベースを多かれ少なかれ整理しました。この全体をキャッシュする方法を考えます。
まず、オブジェクト自体をキャッシュします。 多くの人が推測したか、経験から学んだように、ほとんどの場合、IDでオブジェクトを選択する操作が最も頻繁に行われます。 たとえば、ユーザーのオブジェクトを取得する、Habrahabrデータベース(amen)からこの投稿を取得するなど。
すでに上で説明したように、この作業をアプリケーションに転送するのは不合理です。 分散ロックの庭を植える必要があります。 別の方法で、MongoDBに接続し、スレーブのふりをして、変更ログを受け取り、Memcachedの変更を破棄する非同期アプリケーションを作成します(オブジェクトの_keyプロパティにキーが含まれている場合)。 アプリケーションは非同期であるため、これはすぐに発生しますが、競合は発生しません。 書くのは簡単です、私の実装はこちらです。 さらに、そこにイベントサーバーへの変更の送信も追加したので、サブスクライブしているすべてのクライアントにすぐに転送されるため、どこからでも(コンソールからでも)オブジェクトを変更するだけです。
リクエストのキャッシュとキャッシュの切り下げの動作は少し異なります。 いくつかのアプローチがあります。
- 特定の時間のキャッシュ。 リクエストが同じか、あまり多くない場合は、キャッシュを1秒に1回しか更新できません。これにより、負荷が大幅に削減されます。
- アプリケーションの要求に応じてキャッシュを削除します。 アプローチはかなり退屈ですが、生きる権利があります。
- 1つのジョブを2回実行しないために、ロックサービスを使用します。 間違いなく-これは良いことです。
あなたが直面しなければならないという短所。
- MongoDB-製品は非常に新しく、その中にバグがあり(セグメンテーションフォールト、コアダンプ)、新機能が登場するなど。 本番環境で使用していますが、注意が必要です。 しかし、紛れもないプラスは開発のペースが速いことです(プロジェクトはボランティアだけでなく、完全雇用の人々の会社によっても書かれています)。そのため、迅速なバグ修正を頼りに、問題を解決し、アイデアを実装するのに役立ちます(もちろん優れている場合を除きます)。 商用サポートも利用できます。
- プロパティ名を保存するためのオーバーヘッド。
- デフォルトでは、オブジェクトの最大サイズは4メガバイトです。
- 32ビットマシンでは、1つのデータベースの最大サイズは2ギガバイトです。
フィニータラコメディ!
プロジェクトページ-MongoDB 。ベンチマークMongoDB対MySQLが見つかりました。
この記事では、MongoDBシリーズを開始するリスクがあります。 次回、シャーディング、MapReduceについて詳しく説明し、実例を紹介します。
友人、ご清聴ありがとうございました! 建設的なコメントを歓迎します。
継続公開: 「MongoDB-おいしいコーヒーの醸造」