Улучшение задержки с помощью кэширования в памяти с использованием кофеина

Как мы увеличили задержку на 30%, сохранив при этом стабильность

На сайте Hotels.com мы использовали кэширование в памяти, чтобы уменьшить время отклика p95 нашего приложения с 50 мс до 35 мс. Мы также сократили количество случайных сбоев в базе данных до нуля за последние четыре месяца.

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

Фон

Наша команда, Core-Services Team, поддерживает службу каталогов недвижимости для одного из крупнейших в мире веб-сайтов по бронированию отелей - Hotels.com. При почти 20 000 обращений в секунду и согласованном SLA 50 мс сервис требует времени безотказной работы, близкого к 100%.

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

Технические подробности

Выбор кеша

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

Наши требования к нашему решению для кеширования:

  • Сервис разработан на Scala. Он использует фьючерсы Scala для вызовов базы данных и последующих вызовов. Чтобы кэшировать результат вызовов базы данных или нисходящих вызовов, кеш должен иметь возможность загружать данные с использованием фьючерсов, не блокируя системные потоки.
  • Сервис может поддерживать около 600 000 обращений к базе данных в секунду в трех разных кольцах. Чтобы кэшировать вызовы базы данных, кеш должен без сбоев выдерживать не менее 100 тыс. Операций в секунду.
  • Сервис должен выполнять сериализацию и десериализацию огромного контента без снижения производительности или чрезмерного увеличения потоков JVM.

Сравнение часто используемых решений для кеширования

EhCache

  • EhCache не рассматривался, потому что ему не хватает асинхронной загрузки и встроенной поддержки Scala.

Google Гуава

  • Мы исключили Google Guava. Хотя он может выполнять асинхронную загрузку с разными контекстами выполнения, он использует дополняемые фьючерсы Java, а ScalaCache Guava не предоставляет оболочку для этой функции.
  • ScalaCache ограничивает Guava только строковыми ключами.

Кофеин

  • Мы выбрали кофеин. Scaffeine, оболочка Scala на Caffeine, удовлетворила все наши требования.

Реализация кеша

Поскольку Scala является функциональным языком программирования, очевидным выбором было использовать кеш методов с функциями более высокого порядка. Распространенный метод кэширования - обернуть функцию, которая преобразует пары "ключ-значение", с помощью мемоизации.

Конфигурация кеша

Caffeine предоставляет несколько параметров конфигурации, но нас интересовали в основном размер кеша и политика удаления. Кэш Nimbus предоставляет следующие параметры конфигурации:

  • Начальная емкость
  • Максимальный размер
  • Выселение после записи
  • Выселение после доступа
  • Обновить после записи

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

Полученные результаты

  • Количество обращений к базе данных уменьшено на ~ 280 КБ в секунду (~ 50%) по кольцам Cassandra.
  • Задержки API улучшены на как минимум ~ 30%.
  • Объем памяти всех трех кешей составляет ~ 460 МБ в куче.
  • 400 потоков JVM, увеличение на 50 потоков на узел.
  • Служба каталогов более устойчива к атакам ботов.
  • Одно из колец Кассандры уменьшено до 18 узлов с 24 узлов.
  • Размер кучи увеличен до 6 ГБ с 4 ГБ для размещения кеша и уменьшения паузы при сборке мусора.

Попадания в кеш

Задержка

Планы на будущее

  • Оптимизируйте размер кеша, время выселения и начальную емкость с наименьшим снижением производительности
  • Поэкспериментируйте с централизованным кешем Elasticache для службы каталогов и сравните результаты
  • Внедрение меньшего размера кешей в системе с небольшим объемом памяти для дальнейшего уменьшения задержки API

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

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

Поделитесь с нами, если вам понравилась эта статья, и прокомментируйте, если у вас есть к нам вопросы. И подписывайтесь на нас в блоге Expedia Group Technology, чтобы узнать больше о технологиях.