Parallel Processing
От: dolor Китай  
Дата: 20.02.13 11:04
Оценка:
здравствуйте,

есть код, который обрабатывает однотипные запросы, работает медленновато, а при попытке это дело распараллелить возникло 10 кратное ускорение но и ряд вопросов и проблем

исходные данные:
— обработка запросов требует дополнительных данных, которые сначала ищутся в базе данных, если их там нет, то идут запросы во внешние системы, и ответы сохраняются в базу данных (кеширование)
— результат обработки сохраняется в базу данных, эти данные не шарятся
— дополнительные данные, которые кешируются в базу данных — потенциально шарятся
— каждый поток самостоятельно читает и пишет в базу данных (через хибернейт)
— сама обработка несложная, но и не тривиальная (сложнее чем getThis — setThat)

вопросы:
1. собственно распараллеливание
я набросал свой параллелизатор с Executors.newFixedThreadPool, сабмитом тасков и ожиданием пока все фьючерсы закончат работу, вроде работает
вопрос (странный) — когда мне могут потребоваться такие штуки как Hadoop/MapReduce и тд? только если я захочу задистрибьютить обработку между разными машинами? это в будущем тоже надо будет, стоит ли смотреть в эту сторону?

2. чтение данных
было бы очень круто, если можно было бы подготовить дополнительные данные до запуска задачи и передать их в нее, тогда собственно обработка была бы полностью отвязана от базы данных, но предсказать какие данные потребуются — невозможно (ну или сложно),
в начальной версии 99% времени уходило на открытие и закрытие транзакций (на каждый запрос к базе данных), после перехода на "1 транзакция на 1 запрос" стало гораздо лучше, но все равно много времени уходит на запросы,
есть хибернейтовский кеш второго уровня и он помогает, но хотелось бы большего, во-первых процесс рестартится периодически, во-вторых данных не так уж и много и их вообще бы хорошо бы просто загнать в память сразу, как это сделать? select * from в отдельном потоке? помогут ли распределенные кэши? (oracle coherence? в описании у него тоже что-то про распределенные вычисления говорится, что смущает)

3. запись данных
это вообще нормально, что много потоков пишут паралельно в базу данных? сейчас это создает коллизии для тех данных которые шарятся (нарушает уникальность данных, ну или sql exception если constraint на уникальность данных добавить), а если добавить synchronized на сторон джавы, то вообще дедлокается, виню долгие транзакции и плюс сохранение данных для целей кеширования возможно должно происходить в отдельной короткой транзакции, тогда синкронайзед скорее всего не будет проблемой,
имеет ли смысл вынести все сохранения данных в отдельный поток? скажем изменив таску чтобы она никогда не писала в базу данных, а возвращала данные в параллелизатор?
это правда потребует разбить обработку на 2 подзадачи (обработка двухфазная, вторая фаза использует результаты первой фазы, что работает прозрачно если таска сама пишет результаты первой фазы в базу, и затем снова их читает) — хорошая ли это идея сама по себе — разбитие задач на более мелкие?

вообще хотелось бы отвязать персистенс от обработки, иметь пул данных и потоки которые берут данные из пула и помещают данные в пул, не заботясь о транзакциях и запросах к базе данных, как это сделать?

Целевая архитектура:
один брокер, тащит тысячу задач (номера) из базы, распределяет номера по воркерам (на разных машинах), есть также распределенный кэш (в котором хранятся все данные), воркеры берут задачу по номеру и другие данные из кеша, обрабатывают данные, помещают обратно в кэш -- нормально? как инструменты использовать? или самому понаписать?

Спасибо, частичные ответы, любые намеки и рекомендации приветствуются

21.02.13 15:25: Перенесено модератором из 'Java' — Blazkowicz
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.