web-dev-qa-db-ja.com

Java-大きなファイルを同時に処理する

つまり、私のユースケースの概要は次のとおりです-

定期的(24時間ごと)に、非常に大きなファイル(サイズはMBから数十GBまでさまざまです)を取得しますが、24時間以内に処理する必要があります。処理には、レコードの読み取り、一部のビジネスロジックの適用、レコードを使用したデータベースの更新が含まれます。

現在のソリューションはシングルスレッドバージョンであり、

  1. 最初にメモリ内のファイル全体を読み取ります。つまり、各行を読み取り、POJOを作成します。だから本質的にそれは大きなリストを作成します
  2. 次に、リストを反復処理し、各Pojoにビジネスロジックを適用して、データベースに保存します。

これは、1,000万レコード未満の小さなファイルで機能します。しかし、システムがスケーリングしているため、より大きな負荷、つまりファイルが大きくなっています(たまに1億レコードを超える)。このシナリオでは、タイムアウトが発生します。つまり、24時間以内にファイル全体を処理できません。

そこで、ここで並行性を追加する予定です。

簡単な解決策は

  1. メモリ内のファイル全体を読み取る(現在行っているように、レコードごとにPOJOを作成する)または各レコードを1つずつ読み取り、POJOを作成する
  2. これらのPOJOを同時に処理するスレッドを生成します。

このソリューションはシンプルに見えますが、唯一の欠点は、シングルスレッドであるためファイルの解析に時間がかかる可能性があることです(RAMは問題ではなく、非常に大きなEC2インスタンスを使用しています)。

別の解決策は-

  1. どういうわけかファイルを複数のサブファイルに分割します
  2. 各ファイルを並行して処理する

ファイルを複数の小さなファイルに分割する必要があるため、これは少し複雑に見えます。

ここでのアプローチに関する提案についてのご意見をお待ちしています。

8
AgentX

これを行う最も可能性の高い効率的な方法は次のとおりです。

  • 入力ファイルを読み取る単一のスレッドを用意します。連続して読み取る場合、ハードディスクは最も高速です。
  • しないでください一度にそれをメモリに読み込みます!これは、メモリの無駄遣いであり、処理速度を上げるためにはるかに有効に使用できます。
  • 代わりに、この単一のスレッドにエントリのバンドル(おそらく100、おそらく1000、これはチューニングパラメータ)を一度に読み取らせ、それらをスレッドに送信して処理させます。各行がレコードを表す場合、読み取りスレッドはすべての解析(改行の検索を除く)を処理スレッドに任せることができます。しかし、そうでない場合でも、レコードの解析がボトルネックになることはほとんどありません。
  • 固定サイズのスレッドプール を介してスレッドを処理し、マシン上のCPUコアの数になるようにサイズを選択します。
  • データベースがSQLデータベースの場合は、個々のスレッドが接続プールを介してデータベースにアクセスし、単一のトランザクションでバッチインサートを使用して、エントリの1つのバンドルに対してすべてのDB更新を行うことを確認します。

正しいことを行うためのガイドとなるため、これには Spring Batch を使用することをお勧めします。しかし、それはやや過剰に設計されていて、使いにくいです。

DBがボトルネックになった場合でも、これらすべてが無駄になる可能性があることに注意してください。これは、非常に簡単に起こり得ることです。SQLデータベースは、同時更新の処理が非常に悪いことで有名です。デッドロック。

15

基本的な算術から始めましょう。

(* 24 60 60)
86400

つまり、1日は86400秒です。

(/ 100e6 86400)
1157.4074074074074

つまり、1日に1億レコードを処理するには、1秒あたり1157.4レコードを処理できる必要があります。

さらに一歩進んでください:

(/ 1.0 1157.4074074074074)
0.000864

つまり、1つのレコードをエンドツーエンドで864マイクロ秒で処理できる必要があります。

あなたが何をしようとも、これは真実です。レコードを完全に処理するのに864マイクロ秒以上かかる場合、24時間で1億のレコードを処理することはできません。

「スレッディング」を追加すると、オーバーヘッドが追加され、基盤となるワークロードが削除されないため、状況は悪化し、改善されません。

このクレイジーなラケットで40年近く過ごした後、ファイルをメモリに読み込んでDBMSに結果を書き込んでいると、生きたまま食べているのではないかと思います。

7
John R. Strohm