2013-04-26 11 views
1

我有一個腳本,從文件夾~/xml/中的XML文件導入數據。目前它依次運行,但隨着導入文件數量的增加,它開始耗時太長。運行多個紅寶石進程(數據導入)

我想同時運行腳本的多個副本,但我可以設想出現問題,即兩個腳本都開始處理同一個文件,如果考慮到腳本基本上對對方的存在?

數據庫併發沒有問題,因爲每個導入文件都用於不同的數據庫。

+0

所以問題是每個文件只能處理一次?這些文件是否已經作爲處理的一部分進行移動/歸檔?或者目前該文件夾是否代表一個「批處理」,只處理一次,然後保留原位? – 2013-04-26 15:17:04

+0

是否有某種文件遵循的命名約定?你能讓一個腳本做到平等嗎?另一個做賠率?或文件的其他部分?只要讓腳本採用文件規範,並且它只處理這些文件。 – Doon 2013-04-26 15:36:14

+0

你的腳本如何知道數據文件應該加載到哪個數據庫?向我們展示不同的值或線。寫出來並不難。 – 2013-04-26 15:44:45

回答

7

你在腳本之間沒有任何仲裁,或者沒有做出工作,而且你需要它。

你說這些文件適用於不同的數據庫。腳本如何知道哪個數據庫?難道你不能預處理排隊的文件,並通過將名稱附加到名稱來重命名它們嗎?或者,有一個腳本確定哪些數據在哪裏傳遞,然後將名稱傳遞給執行加載的子腳本?

我會做的更晚,並可能分叉的作業,但線程也可以做到這一點。分叉有一些優點,但線程更容易調試。

不指定足夠了解你的系統給你的代碼,將在下滑,但是這是做什麼用的螺紋總體思路:

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類是關鍵。這就像一個陣列,上面有結冰,用來仲裁對隊列的訪問。這樣想一下:「消費者」,即線程,在空中放置一個標誌以獲得訪問隊列的權限。當獲得該許可時,他們可以popshift或修改隊列。一旦他們完成,權限被賦予下一個線程並且其標誌已經被提交。

我用pop代替shift深奧的原因,但是,如果你的文件有一定的順序加載,他們加入到隊列之前,這樣的順序設置,然後使用shift排序。

我們想存儲正在運行的線程數,所以我們可以在以後使用它們join。這可以讓線程在母親腳本結束之前完成他們的任務。

+0

錫文在這裏爲我們解救。雖然問題不是我的,但是謝謝! – 2013-04-26 16:40:21

+0

這是一個非常棒的答案,我將在星期一進行測試,但這基本上就是我之前所做的,但不知道使用什麼技術(線程,隊列)。爲了回答你的問題,atm腳本使用文件名中的標識符來知道它將進入哪個數據庫。 – 2013-04-27 11:43:39