Применение параллельных вычислений для автоматизации бизнес процессов
Наверняка многие слышали о крупных исследовательских проектах использующих параллельные вычисления для раскрытия структуры гена человека. В таких проектах зачастую используются параллельные вычисления множества серверов и персональных машин участвующих в этом проекте. Параллельные вычисления иногда можно и нужно применять и в более приземленных повседневных задачах. За последние несколько лет ресурсы серверов использующихся для поддержания даже относительно небольших ИТ систем многократно возросли. Большинство серверов используют 4-е и более ядер процессоров. Не учитывая для определенных задач специфику параллельных вычислений, можно потерять значимую часть ресурсов ваших серверов.
Итак, в данной статье речь пойдет о параллельных вычислениях в пределах одного сервера с использованием многопоточности и соответствующим распределением по процессорам. Разумеется, возможность параллельных вычислений является неотъемлемой частью любой OLTP системы претендующей на приемлемую масштабируемость. В этом случае необходимо добиться максимальной параллельности выполнения потоков в разрезе пользователей. В контексте работы MS SQL сервера сессии должны быть максимально независимы друг от друга и не пересекаться на блокировках. При этом полностью от блокировок избавиться будет нельзя, т.к. может возникнуть проблема грязного чтения. В этом случае - цель достичь некоторой золотой середины между независимостью и параллельностью выполнения процессов, при этом не допустить серьезного риска возникновения грязного чтения или дедлоков.
Создание подобной масштабируемой OLTP системы не всегда является тривиальной задачей и этому можно посвятить не одну статью, в данном случае мы рассмотрим другую задачу. А именно ускорение выполнения регламентного процесса выполняемого в монопольном режиме путем распараллеливания.
Задачи распараллеливания отчасти решены в MS SQL – существует специальный параметр (max degree of parallelism) отвечающий за распараллеливание запросов в разрезе процессоров. Использование этого параметра позволяет распараллелить ряд SQL запросов и добиться их ускорения. К сожалению, это происходит не всегда – в ряде случаев может быть обратная ситуация, когда распараллеливаемый запрос выполняется дольше. Кроме этого практически всегда при распараллеливании совокупные затраты времени CPU значительно больше по отношению к выполнению в однопроцессорном варианте. Поэтому этот параметр для OLTP систем практически всегда нужно отключать и запрещать выполнение распараллеливания по умолчанию.
Этим проблемам есть объяснение – не бывает общего решения по распараллеливанию для всех видов задач. Некоторые задачи вообще практически нельзя распараллеливать, некоторые напротив - хорошо поддаются распараллеливанию. (Кому знакомы термины мьютэксы и разработка многопоточных приложений, данная статья вряд ли подскажет что то новое). Рассмотрю несколько примеров из практики, которые показывают область применения алгоритмов распараллеливания.
Расчет заработной платы
Несколько раз возникал вопрос решения проблем длительного времени выполнения регламентных обработок по расчету заработной платы. Разумеется, речь шла о больших объемах измеряемых десятками тысяч сотрудников. Анализ показал, что используемая система на базе 1С для расчета использует большое количество логических операций на клиентской части. На уровне MS SQL не было явно «тяжелых» конструкций, оптимизировав которые можно было бы рассчитывать на серьезный эффект ускорения. Это отчасти обусловлено тем, что сам по себе модуль расчета достаточно сложен в силу специфики российского законодательства, а также учитываются большое количество видов трудовых отношений. Используемое серьезное серверное оборудование было загружено минимально. При этом операции по расчету выполнялись весьма длительное время. Было решено применить для оптимизации этой задачи распараллеливание. В общем-то подобная задача достаточно хорошо распараллеливается, т.к. достаточно мало конкурирующих ресурсов, а также зависящих данных друг от друга. В определенном смысле можно сказать, что с точки зрения бухгалтерского учета расчет зарплаты произвольного сотрудника Х не влияет на расчет зарплаты произвольного сотрудника Y. (разумеется, в конце остается небольшая с точки зрения ресурсов задача агрегации и суммирования результатов).
Это утверждение не всегда справедливо. Например, в некоторых случаях руководители подразделения получают бонусы в зависимости от прибыли по текущему подразделению. В этом случае на бонус руководителя влияет бонус его подчиненных и рассчитывать его необходимо в последнюю очередь. То есть задача расчета бонуса руководителя будет зависеть от задачи расчета бонуса его подчиненным и эти задачи никогда не могут выполняться параллельно.
Концепция реализации достаточно простая. Необходимо посчитать количество сотрудников участвующих в расчете. Исходя из предположения, что время расчета на произвольного сотрудника является постоянной величиной, необходимо этот список поделить на несколько одинаковых по количеству групп. Оптимальное количество групп не всегда равняется количеству процессоров. В некоторых случаях может меньше, т.к. узким местом системы может стать, например дисковая подсистема. А в некоторых случаях, как не удивительно, оптимальное количество может быть больше количества процессоров. Этому тоже есть логическое объяснение, но оно выходит за рамки этой статьи. Далее по этим группам происходит расчет зарплаты в отдельных сессиях 1С. А затем в конце происходит агрегирование результатов.
Все сложности начинаются при реализации. Например, процессы расчета зарплаты по различным сотрудникам в независимых сессиях, несмотря на логическую независимость друг от друга, блокировали друг друга (на уровне внутренних блокировок MSSQL). Для этого пришлось изменить структуру индексов, уровни изоляции а также некоторые типы запросов. Затем узким местом системы стал механизм нумерации новых документов – его также пришлось менять. Были определенные сложности и в создании механизма управления сессиями. Их необходимо было запускать автоматически, определяя сколько их уже запущено, не зависла ли какая либо из них. Необходимо было реализовать механизм контроля выполнения общего процесса и т.п.
В конце концов, когда все было реализовано – получилось уменьшить более чем в десять раз время расчета, при этом загрузив оборудование на 100 процентов. Расчет в каждой из сессий выполнялся практически с одинаковой скоростью и за счет того, что каждая значительно группа была меньше общего списка – совокупное время расчета значительно уменьшилось.
Загрузка данных
В некоторых случаях необходима загрузка данных в ИТ систему. Агент который осуществляет подобную загрузку может работать как в одном потоке, так и в нескольких. Использование нескольких потоков в ряде случаев может существенно ускорить процесс загрузки, обеспечив большую оперативность и увеличение информационных потоков обмена.
К сожалению, это применимо не для всех систем и не для всей области данных. В большинстве случае информация, которая идет в систему зависит друг от друга и важна хронология предоставления этой информации. В этом случае нет возможности взять общую очередь и простым образом разделить ее на равномерные участки и обрабатывать их параллельно. Это возможно, как правило, в редких случаях. Например, в стандартном репликаторе MSSQL триггеры пишут в очередь изменений данные об операциях Insert, Delete, Update. Предполагается, что эти операции можно выполнить независимо друг от друга в случае если нет констрэинтов, вычисляемых полей и явных зависимостей. Кроме того в определенный момент времени может произойти ситуация, когда данные в системе будут несогласованы. Предположим, пройдут изменения по одному потоку в котором есть ссылка на новый элемент X, а в другом потоке где этот элемент создается (Insert) изменения могут еще не пройти. В результате, если в этот момент произойдет чтение по этой области данных, ссылка на элемент Х будет ссылаться на еще не существующий элемент в БД. Это самый простой случай, а ведь есть ситуации когда в зависимости от хронологии проведения документов результаты будут отличаться.
Поэтому область применения параллельных вычислений определяется различными факторами.
Важным условием является, работает ли кто-то с базой в момент загрузки данных. Как правило, параллельная загрузка необходима в случае возникновения больших очередей обмена. Это может произойти в случае длительного отсутствия связи источника и приемника. В этом случае в ночное время (если в это время с базой никто не работает, например система не 24*7) необходимо будет максимально использовать серверные ресурсы, для того чтобы в минимальный срок перенести всю очередь. Далее важно определить, а можно ли разбить очередь на группы изменений по объектам, которые относительно не зависят друг от друга.
Например, загрузка товаров по различным складам или загрузка различных видов документов использующих независимые контуры.
Вообще использование многопоточности является необходимым условием любого эффективного репликатора. В некоторых проектах применяя многопоточную загрузку наша проектная группа добивалась более чем 8-и кратного ускорения загрузки данных. Компания «СофтПоинт» успешно применяет технологию распараллеливания в проектах по оптимизации и построения распределенных систем.
Источник: Softpoint