1

フォルダー内の XML ファイルからデータをインポートするスクリプトがあります~/xml/。現在は順次実行されていますが、インポート ファイルの数が増えるにつれて時間がかかりすぎています。

スクリプトの複数のコピーを並行して実行したいのですが、両方のスクリプトが同じファイルの処理を開始するという問題があると考えられます。スクリプトは基本的に互いの存在を認識していないことを考えると、これをどのように回避しますか?

各インポート ファイルは異なるデータベース用であるため、データベースの同時実行性に問題はありません。

4

1 に答える 1

8

スクリプト間で調停したり、作業を分担したりする必要はありません。それが必要です。

ファイルは異なるデータベース用であるとあなたは言います。スクリプトはどのデータベースをどのように認識しますか? キューに入れられたファイルを前処理して、名前に何かを追加して名前を変更できませんか? または、どのデータがどこに行くかを決定し、ロードを行うサブスクリプトに名前を渡すスクリプトがありますか?

私は後者を行い、おそらくジョブをフォークしますが、スレッドもそれを行うことができます。フォークにはいくつかの利点がありますが、スレッドの方がデバッグが容易です。

スライドインするコードを提供するためにシステムについて十分に指定していませんが、これはスレッドを使用して何をすべきかの一般的な考え方です:

require 'thread'

file_queue = Queue.new
Dir['./*'].each { |f| file_queue << f }

consumers = []
2.times do |worker|
  consumers << Thread.new do
    loop do
      break if file_queue.empty?
      data_file = file_queue.pop
      puts "Worker #{ worker } reading #{ data_file }. Queue size: #{ 1 + file_queue.length }\n"
      num_lines = 0
      File.foreach(data_file) do |li|
        num_lines += 1
      end
      puts "Worker #{ worker } says #{ data_file } contained #{ num_lines } lines.\n"
    end
  end
end

consumers.each { |c| c.join }

実行後、コンソールに次のように表示されます。

Worker 1 reading ./blank.yaml. Queue size: 28
Worker 0 reading ./build_links_to_test_files.rake. Queue size: 27
Worker 0 says ./build_links_to_test_files.rake contained 68 lines.
Worker 0 reading ./call_cgi.rb. Queue size: 26
Worker 1 says ./blank.yaml contained 3 lines.
Worker 1 reading ./cgi.rb. Queue size: 25
Worker 0 says ./call_cgi.rb contained 11 lines.
Worker 1 says ./cgi.rb contained 10 lines.
Worker 0 reading ./client.rb. Queue size: 24
Worker 1 reading ./curl_test.sh. Queue size: 23
Worker 0 says ./client.rb contained 19 lines.
Worker 0 reading ./curl_test_all_post_vars.sh. Queue size: 22

それは削減されましたが、あなたはアイデアを得る.

RubyのQueueクラスが鍵です。これは、キューへのアクセスを調停するアイシングを塗った配列のようなものです。このように考えてみてください。「消費者」、つまりスレッドは、キューにアクセスするための許可を得るためにフラグを立てます。その許可が与えられると、キューを変更しpopたり、変更したりできます。shiftそれらが完了すると、フラグが立てられた次のスレッドに許可が与えられます。

難解な理由popで代わりに使用しますが、ファイルを特定の順序でロードする必要がある場合は、キューに追加する前に並べ替えて順序を設定し、 .shiftshift

後で実行できるように、実行中のスレッドの数を保存しjoinます。これにより、スレッドはマザー スクリプトが終了する前にタスクを完了できます。

于 2013-04-26T15:36:57.760 に答える