質問

私は電子メール サービスとソーシャル ネットワークの中間のような Web アプリに取り組んでいます。将来的に大きくなる可能性を感じているので、拡張性が気になります。

1 つの集中管理された MySQL/InnoDB データベースを使用し、必要なときにパーティション分割する代わりに、アクティブ ユーザーごとに個別の SQLite データベースを作成することにしました。「シャード」ごとに 1 人のアクティブ ユーザー。

そうすれば、データベースのバックアップは各ユーザーのコピーと同じくらい簡単になります。 小さい データベース ファイルを 1 日に 1 回リモートの場所に送信します。

スケールアップは、新しいファイルを保存するためにハードディスクを追加するのと同じくらい簡単です。

アプリが単一サーバーを超えた場合は、GlusterFS を使用してファイル システム レベルでサーバーをリンクし、アプリを変更せずに実行することも、各サーバーが隣接するサーバーにある sqlite ファイルを操作できるようにするシンプルな SQLite プロキシ システムを構築することもできます。

各 HTTP リクエストは一度に 1 つまたは 2 つのデータベース ファイル (数千件中) にのみアクセスし、SQLite は読み取り時にのみブロックするため、同時実行性の問題は最小限になります。

このアプローチにより、アプリが適切に拡張でき、多くの優れた機能をサポートできるようになると確信しています。 個性的 特徴。私の賭けは間違っているでしょうか?何か足りないものはありますか?

アップデート 私はそれほど極端ではない解決策を採用することにしましたが、これは今のところうまく機能しています。私は固定数のシャード (正確には 256 個の sqlite データベース) を使用しています。各ユーザーは、単純なハッシュ関数によってランダムなシャードに割り当てられ、バインドされます。

私のアプリのほとんどの機能では、リクエストごとに 1 つまたは 2 つのシャードのみにアクセスする必要がありますが、特に、ユーザーに応じて 256 個のシャードのうち 10 ~ 100 個の異なるシャードに対して単純なクエリを実行する必要がある機能があります。テストによると、すべてのデータが RAM にキャッシュされている場合、所要時間は約 0.02 秒以下です。それで生きていけると思います!

アップデート2.0 アプリを MySQL/InnoDB に移植したところ、通常のリクエストではほぼ同じパフォーマンスを得ることができましたが、シャード ウォーキングが必要な 1 つのリクエストでは、innodb の方が 4 ~ 5 倍高速でした。このような理由と他の理由で、私はこのアーキテクチャを削除しますが、どこかで誰かがそれを使用できることを願っています...ありがとう。

役に立ちましたか?

解決

これが失敗するのは、いわゆる「シャード ウォーキング」を実行する必要がある場合です。これは、多数の異なるユーザーのすべてのデータを検索することです。このような特定の種類の「クエリ」はプログラムで実行する必要があり、各 SQLite データベースに順番に問い合わせる必要があり、サイト内で最も遅い部分となる可能性が非常に高くなります。これは、データが別々のデータベースに「シャード化」されているシステムでは共通の問題です。

すべてのデータがユーザーにとって自己完結型である場合、これはかなり適切に拡張できるはずです。これを効果的な設計にするための鍵は、データがどのように使用される可能性があるか、および 1 人の個人からのデータが相互作用するかどうかを知ることです。 (あなたのコンテキスト内で) 別のデータからのデータを使用します。

ファイル システム リソースにも注意する必要があるかもしれません (SQLite は素晴らしく、素晴らしく、高速です)。ただし、「標準データベース」 (つまり、MySQL、PostgreSQL など) はその設計方法によるものです。提案された設計では、その一部が失われることになります。

他のヒント

メンテナンスの悪夢のように思えます。これらすべての DB でスキーマが変更されるとどうなりますか?

考えられる問題の 1 つは、ユーザーごとに 1 つのデータベースを使用すると、ディスク領域と RAM の使用効率が非常に低くなり、ユーザー ベースが増加するにつれて、軽量で高速なデータベース エンジンを使用する利点が完全に失われることです。

この問題に対する考えられる解決策は、「ミニシャード" 最大 1024 個の SQLite データベースで構成され、 それぞれ 100 ユーザー. 。データがより効率的にパックされるため、これはユーザーごとの DB アプローチよりも効率的です。また、Sqlite を使用しているため、Innodb データベース サーバーのアプローチよりも軽量です。

同時実行性もかなり優れていますが、クエリはそれほどエレガントではありません (shard_id の厄介さ)。どう思いますか?

http://freshmeat.net/projects/sphivedb

SPHiveDB は sqlite データベース用のサーバーです。JSON-RPC over HTTP を使用して、SQLite データベースを使用するネットワーク インターフェイスを公開します。複数の SQLite データベースを 1 つのファイルに結合することをサポートします。複数のファイルの使用もサポートしています。これは、ユーザーごとに 1 つの SQLite データベースという極端なシャーディング スキーマ向けに設計されています。

ユーザーごとに個別のデータベースを作成している場合、関係を設定していないように思えます...では、そもそもなぜリレーショナル データベースを使用するのでしょうか?

基本的にサーバー側の SQLLIte データベースをクライアントのバックアップおよび同期コピーとして使用したいと考えていたため、これと同じアーキテクチャを検討しています。すべてのデータに対してクエリを実行するための私のアイデアは、全文検索に Sphinx を使用し、すべてのデータのフラット ダンプから Scribe への Hadoop ジョブを実行し、結果を Web サービスとして公開することです。ただし、この投稿は私に少し考える機会を与えてくれるので、人々が引き続き意見を返してくれることを願っています。

データがこれほど簡単にシャーディングできるのであれば、標準のデータベース エンジンを使用してみてはいかがでしょうか。また、DB がボトルネックになるほど大規模に拡張する場合は、異なるインスタンスの異なるユーザーでデータベースをシャーディングしてはいかがでしょうか。効果は同じですが、多数の小さなデータベースを使用する必要はありません。

実際には、どのユーザーにも属さない共有データが少なくともいくつかあると考えられ、複数のユーザーのデータに頻繁にアクセスする必要があるでしょう。ただし、これによりどちらのシステムでも問題が発生します。

もちろん、ユーザーごとに 1 つのデータベースを使用すると、個々のユーザーのデータを復元するのが非常に簡単になりますが、 @ジョン スキーマの変更には多少の作業が必要になるとのことでした。

難しくするほどではありませんが、簡単ではなくなるには十分です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top