11 мая 2022 г.

Mystery of link imbalance #2: как можно починить MRU-пул

Я не удержался, и еще поэкспериментировал с симуляцией link imbalance из предыдущего поста. Там есть вопрос: как эту проблему исправить? Как сделать так, чтобы трафик не собирался на один-единственный канал?

Инженеры фейсбука порешали проблему тем, что сменили в пулах соединений стратегию MRU на LRU. LRU хорошо балансирует нагрузку – старается все соединения в пуле использовать в равной степени – и как бы соединения в пулах не сортировались, на сколько-либо длинной дистанции все равно все каналы будут задействованы примерно одинаково.

Но у MRU есть преимущества: пул с такой стратегией минимизирует количество активных соединений. Это уменьшает нагрузку на сервер БД, плюс небольшое число активных соединений вероятнее будет горячим в кэше, как на стороне клиента, так и на стороне сервера БД. В статье не пишут, почему изначально в фейсбуке был выбран MRU-пул, но можно предположить, что именно поэтому.

Однако кажется, что можно сохранить преимущества MRU, но предотвратить link imbalance.

Надо просто иначе интерпретировать used в most-recently-used. Ведь "использование" соединения это не один момент времени, а интервал – от момента, когда соединение взяли из пула, до момента, когда его вернули. Любой момент внутри этого интервала можно взять за основу для сортировки соединений по "времени последнего использования" – и преимущества MRU будут сохраняться.

Обычно берется верхняя грань этого интервала, т.е. момент возвращения соединения в пул – это удобно для реализации, ведь можно не поддерживать упорядоченный список соединений, а просто хранить соединения в стеке.

Но такой выбор создает сцепку между длительностью использования соединения (длительностью исполнения запроса), и порядком соединений в пуле – именно поэтому более медленные соединения всплывают наверх, и поэтому возникают предпосылки для link imbalance issue.

Если же за основу для MRU взять момент, когда соединение берется из пула, то связь между длительностью запроса и порядком соединений в пуле исчезнет, и соединения перестанут сортироваться по скорости исполнения запросов. По-идее, это должно убрать предпосылки для link imbalance issue.

Я проверил эту идею на симуляции, и она действительно работает: на графиках ниже результаты двух одинаковых симуляций: в обеих 25 клиентов, 50 соединений в пуле у каждого клиента. Но в одной симуляции MRU-пул сортирует соединения по времени взятия их из пула, а в другой – по времени возвращения в пул.

Явно видно, что link imbalance issue воспроизводится только в одной из симуляций – в той, где за "момент использования" принимается момент возвращения соединения в пул. Если же за "момент использования" принять момент взятия соединения из пула, то link imbalance перестает возникать.

(Обратите внимание, что на графиках масштаб по вертикальной оси различается в 30 раз – 1500% против 50%)

Для уверенности я обсчитал сценарий, где прилетает не одна пачка почти одинаковыхи запросов, а несколько – на случай, если есть какой-то накопительный эффект – но нет, похоже, стратегия MRU использующая момент начала использования соединения достаточно иммунна к link imbalance:

Уточню: смысл не в том, что инженеры фейсбука глупые, что просмотрели такой простой фикс – это всего лишь симуляция, она может очень сильно отличаться от реальности, и у инженеров фейсбука мог быть миллион веских причин все-таки перейти на LRU, вместо того, чтобы пытаться "починить" MRU-стратегию. Скорее, этот результат любопытен потому, что он демонстрирует, какой элемент тут – ключевой для возникновения этого любопытного поведения. Что по-минимуму можно изменить в системе, чтобы она перестала демонстрировать link imbalance metastable issue.

Комментариев нет:

Отправить комментарий