🚀 Как ускорить распределенные системы: 8 стратегий снижения времени ожидания

Знакомая ситуация: открываешь приложение, а оно думает... и думает... и думает. У нас есть для тебя восемь отличных рецептов, как превратить «задумчивое» приложение в настоящего спринтера. Готов прокачать свою систему? Тогда поехали!

Этот материал взят из нашей еженедельной email-рассылки, посвященной бэкенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест.

Время ожидания (latency) – это время, которое требуется на доставку пакета данных от источника к пункту назначения. В контексте распределенных систем это особенно важно: данные хранятся и обрабатываются на разных серверах, и высокая задержка может сделать приложение практически непригодным к использованию. А медленные приложения раздражают пользователей даже больше, чем совсем неработающие – те, по крайней мере, не тратят зря их время. Поэтому разработчикам стоит уделять особое внимание выбору оптимальной стратегии (или их комбинации) для максимального снижения времени ожидания.

Кэширование

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

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

Типичная схема кэширования

CDN (сеть доставки контента)

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

Если на сервере CDN уже есть закэшированный контент, он доставляется пользователю напрямую из кэша, что исключает необходимость запрашивать его у исходного сервера. Это сокращает расстояние, которое данные должны пройти, и минимизирует время отклика.

Два сценария работы сети доставки контента

Балансировка нагрузки

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

Когда клиент отправляет запрос в распределенную систему, балансировщик нагрузки становится первым пунктом контакта. Он получает запрос и перенаправляет его на один из доступных серверов, исходя из заранее заданных алгоритмов. Наиболее распространенные алгоритмы балансировки нагрузки включают:

  1. Круговое распределение. Запросы равномерно распределяются по серверам, один за другим, по кругу. Например, если у вас есть три сервера, первый запрос идет на первый сервер, второй на второй, третий на третий, а четвертый снова на первый и так далее.
  2. Наименьшее количество подключений. Балансировщик направляет запрос на сервер, который имеет наименьшее количество текущих соединений. Этот метод помогает равномерно распределять нагрузку, когда выполнение запросов занимает разное время.
  3. Хеширование IP. Метод использует хеш-функцию, которая вычисляется на основе IP-адреса клиента. Это позволяет направить запросы от одного и того же клиента всегда на один и тот же сервер.

Подробнее алгоритмы балансировки нагрузки разбирались здесь: «🏄 6+ главных алгоритмов балансировки нагрузки»

Балансировщик распределяет нагрузку в соответствии с определенным алгоритмом

Асинхронная обработка

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

В модели асинхронной обработки, когда пользователь запускает долгосрочную задачу, например, генерирует сложный отчет или обрабатывает большой набор данных, система сразу же подтверждает получение запроса и отправляет уведомление пользователю. За кулисами задача помещается в очередь.

Отдельный фоновый процесс (или пул процессов) постоянно следит за этой очередью, извлекая задачи, как только они становятся доступными. Рабочий процесс выполняет долгосрочную задачу асинхронно, не блокируя основной поток приложения и не влияя на отзывчивость системы. Это позволяет системе оставаться быстрой и отзывчивой, даже если некоторые операции занимают много времени.

Индексирование в базах данных

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

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

Сжатие данных

При передаче данных в распределенных системах важно предусмотреть способ уменьшения среднего объема пакетов: чем больше объем данных, тем больше пропускной способности сети они потребляют, тем выше задержка и тем сильнее снижается общая производительность системы.

Алгоритмы сжатия находят и удаляют повторяющиеся элементы в данных, заменяя их более компактными представлениями. В результате:

  • Уменьшается объем трафика и нагрузка на сеть.
  • Сокращается время ожидания.
  • Требуется меньше вычислительных ресурсов для передачи и обработки данных.

Предварительное кэширование

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

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

Постоянные соединения

TCP-рукопожатие (процесс установления соединения между клиентом и сервером) требует минимум 3 этапа обмена данными:

  • Клиент: «Привет, хочу установить соединение».
  • Сервер: «Ок, я готов»
  • Клиент: «Отлично, начинаем общение».

Каждое такое «рукопожатие» занимает время и ресурсы. Постоянное соединение (Keep-Alive) решает эту проблему и позволяет существенно ускорить работу веб-приложений за счет повторного использования существующих соединений вместо создания новых:

  • Соединение не закрывается сразу после завершения запроса, а остается активным некоторое время.
  • Новые запросы используют уже установленное соединение.
  • Не нужно тратить время на новое «рукопожатие».
TCP-рукопожатие – трехэтапная процедура

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

admin
30 июня 2018

Шаблоны проектирования в Python: для стильного кода

Многие шаблоны проектирования встроены в Python из коробки, а другие очень ...
Библиотека программиста
12 июля 2017

Что такое Docker, и как его использовать? Подробно рассказываем

Разберем по косточкам, ведь Docker – это мощный инструмент, и огромное коли...