2013-04-26 6 views
1

У меня есть сценарий, который импортирует данные из файлов XML в папку ~/xml/. В настоящее время он работает последовательно, но он начинает занять слишком много времени, пока увеличивается количество файлов импорта.Выполнение нескольких процессов ruby ​​(импорт данных)

Я хотел бы запускать несколько копий сценария параллельно, но я могу предусмотреть, что возникают проблемы, при которых оба сценария начинают обрабатывать один и тот же файл, как бы вы обошли это, учитывая, что сценарии по существу не знают друг друга существование?

Нет проблем с параллелизмом базы данных, поскольку каждый файл импорта предназначен для другой базы данных.

+0

Таким образом, проблема в том, что каждый файл должен обрабатываться только один раз? Файлы уже перемещены/заархивированы как часть обработки? Или в настоящее время папка представляет собой «пакет», которая обрабатывается только один раз, а затем остается на месте? –

+0

есть какое-то соглашение об именах, в котором следуют файлы? Не могли бы вы сделать 1 скрипт? другие делают шансы? или какой-либо другой части файла? Просто заставьте скрипт взять спецификацию файлов и обрабатывать только те файлы. – Doon

+0

Как ваши скрипты знают, в какую базу данных должен загружаться файл данных? Покажите нам разные значения или строки. Это не сложная проблема. –

ответ

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's Queue класс - это ключ. Это похоже на массив с обледенением на нем, который разрешает доступ к очереди. Подумайте об этом так: «потребители», т. Е. Потоки, поставьте флаг в воздухе, чтобы получить разрешение на доступ к очереди. При предоставлении этого разрешения они могут pop или shift или изменить очередь. Как только они будут сделаны, разрешение будет передано следующему потоку с его флагом вверх.

Я использую pop вместо shift эзотерических причин, но, если ваши файлы должны быть загружены в определенном порядке, сортировать их, прежде чем они будут добавлены в очередь, так что порядок установлен, то используйте shift.

Мы хотим сохранить количество потоков, чтобы мы могли join их позже. Это позволяет потокам выполнять свои задачи до окончания сценария.

+0

Оловянный человек здесь для нашего спасения. Хотя проблема не моя, спасибо в любом случае! –

+0

Это превосходный ответ, я буду тестировать в понедельник, но это в основном то, что я был после, но не знал, какие методы использовать (Threads, Queues).Чтобы ответить на ваш вопрос, сценарий atm использует идентификатор в имени файла, чтобы узнать, в какую базу данных он входит. –

Смежные вопросы