Глава 7. Паттерн Scatter/Gather 129
Это значит, что, когда пользователь запрашивает все документы, содержащие слова «кот» и «собака», его запрос отправляется всем терминальным узлам Scatter/Gather-дерева. Каждый тер-минальный узел возвращает набор известных ему документов, содержащих слова «кот» и «собака». Ранее корневой узел от-вечал за пересечение наборов документов, возвращенных для каждого поискового терма. В случае шардированного сервиса корневой узел отвечает за вычисление теоретико-множествен-ного объединения наборов документов, возвращенных шарда-ми, которое и является конечным результатом, отправляемым пользователю.
Еще раз посмотрите на рис. 7.3. Первый терминальный узел обслуживает документы 1–10 и возвращает {doc1, doc5} . Второй терминальный узел обслуживает документы 11–20 и возвращает {doc15} . Третий терминальный узел обслуживает документы 21–30 и возвращает {doc22, doc28} . Корневой узел объединяет ответы и возвращает множество {doc1, doc5, doc15, doc22, doc28} .
Выбор подходящего количества терминальных узлов
Может показаться, что в рамках паттерна Scatter/Gather всегда имеет смысл реплицировать вычисления на как можно большее количество узлов. Распараллеливая вычисления, вы сокраща-ете время обработки конкретного запроса. Увеличение степени распараллеливания несет с собой дополнительные расходы, поэтому для достижения максимальной производительности в распределенной системе чрезвычайно важно правильно вы-брать количество терминальных узлов.
Чтобы понять, почему так происходит, следует рассмотреть две вещи. Во-первых, обработка каждого конкретного запроса
130Часть II. Паттерны проектирования обслуживающих систем подразумевает определенные накладные расходы. Требует-ся время на анализ запроса, на его пересылку по сети и т. д. В общем случае накладные расходы на обработку запроса опе-рационной системой постоянны и сравнительно невелики по отношению ко времени обработки запроса в пользовательском режиме. Соответственно, при оценке производительности реализации паттерна Scatter/Gather ими, как правило, можно пренебречь.
Важно, однако, понимать, что объем накладных расходов реализации паттерна Scatter/Gather растет с увеличением количества терминальных узлов. Поэтому, несмотря на их не-большой объем, с ростом степени распараллеливания расходы на них со временем могут превысить расходы на реализацию бизнес-логики приложения. А это значит, что рост производи-тельности за счет распараллеливания носит асимптотический характер.
Помимо того что добавление терминальных узлов может и не ускорить обработку запросов, Scatter/Gather-системы также подвержены «эффекту отстающего». Чтобы понять причину этого, важно помнить, что в Scatter/Gather-системе корневой узел сможет отправить ответ конечному пользователю не ранее, чем дождется ответа от всех терминальных узлов. По-скольку необходимо получить данные от всех узлов, общее время обработки запроса определяется временем обработки запроса самым медленным узлом. Попытаемся понять, как это влияет на производительность, и рассмотрим сервис, в ко-тором 99-й процентиль задержки составляет 2 секунды. Это значит, что в среднем один из 100 запросов будет обработан с задержкой 2 секунды и более. Иными словами, обработка запроса займет 2 секунды и более с вероятностью 1 %. На пер-вый взгляд, это совершенно приемлемо, так как только один из 100 запросов будет обрабатываться медленно. Но в систе-Глава 7. Паттерн Scatter/Gather 131
мах, построенных по принципу Scatter/Gather, дела обстоят несколько иначе. Поскольку время обработки запроса опре-деляется самым медленным ответом, нам приходится рассма-тривать не один запрос, а все запросы, распределенные между
терминальными узлами системы.
Посмотрим, что произойдет, если распределить запросы на пять терминальных узлов. Вероятность того, что обработка за-проса одним из терминальных узлов займет 2 секунды и более, равна 5 % (0,99 × 0,99 × 0,99 × 0,99 × 0,99 = 0,95). А это значит, что 99-й процентиль задержки единичного запроса становится 95-м процентилем задержки всей Scatter/Gather-системы. Даль-ше — хуже: если распределить нагрузку на 100 терминальных узлов, то общая средняя задержка обработки почти наверняка составит 2 секунды.
Из перечисленных выше проблем можно сделать несколько выводов:
в силу накладных расходов, имеющих место в каждом узле, повышение степени параллелизма не всегда ускоряет работу системы;
в силу «эффекта отстающего» повышение степени паралле-лизма не всегда ускоряет работу системы;
Читать дальше