2012-03-22 6 views
0

1秒に1つのホストに5〜10個の新しいデータベースレコードを生成するアプリがあります。データをリモートデータベースにすばやく書き込む

レコードにチェックは必要ありません。それらは単にリモートデータベースに記録する必要があります。

私はクライアントアプリケーション用にJavaを使用しています。

データベースはサーバーの後ろにあります。

送信データでアプリが待たされることはありません。だからおそらく、少なくとも1つのレコードをリモートサーバに送信することは、少なくとも同期的にはうまくいかない。

送信データは失敗してはなりません。私のアプリはサーバーからの回答を必要としませんが、サーバーに正しく到着するように100%安全でなければなりません(例えばhttp url接続(TCP)を使って保証する必要があります...?)。

私は、このためのいくつかのアプローチを考えた:

  • は別のスレッドで送信データのコードを実行します。

  • データをメモリにのみ保存し、特定の回数後にデータベースに送信します。

  • ローカルデータベースにデータを格納し、要求によってサーバーによって送信/受信されます。

これはすべて意味がありますが、私はこのことについてnoobであり、いくつかの標準的なアプローチがあります。行く方法についてはわからない。

答えて

2

要件はあまり明確ではありません。私の最善の答えは、あなたの質問に進み、ポイントごとに正しい方向に向けることです。

  • "記録には何も確認する必要はありません。"と "私のアプリは答えが必要ではありませんが、サーバーに正しく到着するまで100%安全でなければなりません。

回答を送信せずにデータが受信されたことをクライアントがどのように正確に把握していますか?あなたは常に例外処理をアプリに書いて、何らかの理由でクライアントの接続やデータが送られてくる状況に対処する計画を立てるべきです。あなたが作ったこの2つのステートメントは、お互いに矛盾しているようです。応答は必要ありませんが、データが到着したことを知る必要がありますか?あなたのアプリは受信しているデータを確認するためにクリスタルボールを使用する予定ですか(もしそうなら、私はクリスタルボールを私に送ってください - 私は株式市場を短くするために使いたいです)。

  • 「別のスレッドで送信データのコードを実行する」と「メモリ内のデータを保存し、後で送って、」と「ローカルにデータを保存し、それがサーバーによって引っ張ら持っている」、および「データをすることができます送信私のアプリを待たせない "。

いいえ、非ブロッキングI/Oが必要なようです。しかし、実際には、非ブロックI/Oであっても、実際にデータを送信するには、まだの一部分がになります。私の質問は、なぜ非ブロッキングおよび/または高速I/Oを求めるのですか?データ転送が非常に高速だった場合、それがノンブロッキングでないかどうかは本当に問題になりますか?これはあなたのところでの設計上の決定ですが、あなたの質問からなぜこれが必要なのかは明らかではありません。なぜならが必要なのです。

データをメモリに入れて後で送信する限り、これは実際にノンブロッキングでもマルチタスクでもありません。それはちょうど将来の時間まで仕事をやめているだけです。私はソフトウェアの先延ばしを考えています。このメソッドは、データを処理するためにアプリが行う必要のある時間や作業量を削減するものではなく、将来のある日にそれを置きます。これは、大量のデータを「バッチ処理」することに何らかの利点がない限り、何も得られません。

メモリ内のアイデアも一時バッファのように聞こえます。多くのI/Oストリームの実装には、ネットワークカード上のバッファだけでなく、ルータ上のバッファなども組み込まれたバッファが組み込まれます。コードに別のバッファを追加することはできませんあなたがなぜこれが助けになると思うのか正当化できない限り、表面上には何か意味があるようです。つまり、バッファを導入して解決しようとしている、実際に経験した問題は何ですか?また、このデータをどのように送信するか(つまり、どのネットワークI/Oクラスを選択するか)によっては、クラス実装の一部としてノンブロッキングI/Oが含まれる可能性があります。

次に、別のスレッドでデータを送信する場合は、ノンブロッキングI/Oが必要な場合は問題ありませんが、(1)前にソフトウェアの設計上、なぜそれが良いアイデアなのかを正当化する必要がありますあなたは、あなたのアプリに複雑さを加えるので、特定の、本当の問題を解決しない限り(つまり、保留中のI/O操作のために凍っている/応答しないようにするべきあなたのアプリのUIを持っている)それはちょうど合併症を追加し、あなたはそれから何か追加されたパフォーマンスを得ることはありません。 (2)スレッドを使用して、やはり基本的に作業を先延ばしにするという一般的な誘惑があります。ワークを別のスレッドに置いても、実行する必要がある作業の総量や、アプリケーションがその機能を果たすために消費するI/Oの合計量が減るわけではありません。別のスレッドで処理するだけです。これは非常に有益な時代であり、アプリにとっては正しい決定だと思うかもしれませんが、あなたの説明から、多くの要求された機能を見ることができますが、そのバックアップの正当性(または解決しようとしている問題の説明)これらの機能/デザインの選択肢は、最終的にあなたが行く方向を決めるものです。

最後に、サーバをプルするのではなく、サーバにプルするのであれば、ここではロールを反転してサーバをクライアントとして動作させ、クライアントサーバー。 「クライアント」と「サーバー」は相対的な用語であり、サーバーはサービスを提供していることを認識してください。単にロールを反転させるだけでは、実際には何も変わらず、クライアント/サーバーの役割をソフトウェアの一部から他の部分に変えるだけです。ラベル自体は単なるラベルです。どの部分がサービスを提供しているのか、どの部分がサービス(クライアント)を消費しているのかを知る便利な方法です。

  • "毎秒1ホストで5〜10個の新しいデータベースレコードを生成するアプリがあります。"

これは問題ではありません。まともなDBサーバーは、この種の作業を非常に低い負荷として扱います。サーバーからの速度/応答性に関するより大きな懸念事項は、ネットワーク遅延(ネットワークを介してこのデータを転送していることを前提としています)や、I/Oの選択に関するその他の要因によって影響を受けます。 1秒あたり10レコード - つまり、全体のスループット。

0

クライアントアプリケーションをブロックしたくない場合は、別のスレッドからデータを送信する必要があります。

これを実行すると、作成するのと同じくらい速く、データベースにレコードを送信できるかどうかが重要です。私はそれを1つずつ送信して作業を開始してから、十分でない場合は、それらをメモリー内のキューに入れ、バッチで更新します。レコードが生成される割合を決定するものが何であるかわからないので、もっと言い表すのは難しいです。

あなたはデータベースへの書き込み方法を言っていません... JDBC? ORMはHibernateのようですか?しかし原則は同じです。

1

データをキューに入れてスレッドで送信する場合、レートが1秒あたり5〜10で、クライアントが1つだけの場合は問題ありません。複数のクライアントがある場合、データベースの挿入が遅くなるまで、問題が発生する可能性があります。 「データ送信は失敗してはいけません。これは、特にマシンやネットワークの障害に直面して、はるかに難しい要件です。

以下のシナリオを考えてください。データベースが効率的に処理できるクライアント数よりも多くのクライアントがあり、ユーザーの1人は高速タイピストです。インサートは自分のアプリでメモリにバックアップを開始します。彼らは仕事を終え、最後のものが実際にデータベースにアップロードされる前にシャットダウンします。または、データが送信される前、または送信中にマシンがクラッシュします。データベースの送信中にクラッシュし、ネットワークの問題により、クライアントはトランザクションが完了していないことを実際には知ることができません。

これらの問題(ほとんどの場合、ほとんどの場合)を避ける簡単な方法は、データをどこかでコミットして続けるまでユーザーを待たせることです。データベースを十分に高速に挿入できる場合は、よりシンプルなスキームを採用することができます。そうでない場合は、より創造的でなければなりません。

たとえば、ユーザーがサブミットして別のスレッドからアップロードしたときに、ローカルにデータをディスクに書き込むことができます。このシナリオは、送信されたものとしてマークされているものをマークするのに十分スマートである必要があります(削除すると効果があります)。起動時にスキャンを再スキャンし、未送信の作業を送信する機能があります。また、ネットワークや集中型サーバーの障害の場合でも試行錯誤を続ける能力が必要です。

サーバー側が重複を検出する方法も必要です。クライアントマシンはデータを送信し、送信済みとしてマークする前にクラッシュする可能性があるため、再起動すると、再度送信されます。悪いネットワーク接続がある場合も同じ状況が発生する可能性があります。クライアントはそれを送信し、サーバーからの確認を受け取ることはできません。タイムアウトして、それをやり直してしまいます。

2

残念なことにenterprisey、正式なこれは、耐久性のあるメッセージキューを使用することです。あなたのアプリはキューにメッセージを送り、バックエンドアプリは受信してデータベースに格納します。キューがメッセージを受け入れると、送信者、受信者、またはキューブローカ自体がクラッシュしても、受信者がそのメッセージを使用できるようになります。

私のマシンでは、HornetQを使用すると、短いテキストメッセージを構築して耐久性のあるキューに送信するには約1ミリ秒かかります。これは、Webリクエストの処理の一環として、追加の遅延を大幅に増加させることなく行うことができます。良いメッセージキューは、毎秒10メッセージのスループットをサポートします。 HornetQは、8.2 million messages per secondの扱いとしてベンチマークされています。

メッセージキューは設定して使用するのが難しくないことを付け加えておきます。私はHornetQをダウンロードし、それを数分間で稼働させました。キュー(ネイティブHornetQ APIを使用)を作成し、JMS APIを使用してメッセージを送受信するために必要なコードはless than a hundred linesです。

関連する問題