Правила для оптимизированного механизма кеширования

На каждую сложную проблему есть ясный, простой и неправильный ответ.

Давайте посмотрим, как выглядит типичный рабочий процесс пропуска кеша.

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

Кончик

Используйте Бит, чтобы легко инкапсулировать модули / компоненты со всеми их зависимостями и настройками. Делитесь ими в Bit’s Cloud, сотрудничайте со своей командой и используйте их где угодно.



ЗАКРЫТЬ. ПОДЕЛИТЬСЯ. СОТРУДНИЧЕСТВО. ПОВТОРНОЕ ИСПОЛЬЗОВАНИЕ.

| Bit.dev |

Давайте создадим небольшую демонстрацию, чтобы отразить это.

  • Мы смоделируем запрос кеша, который возвращается через 5 мс.
  • Мы смоделируем запрос к базе данных, который возвращается через 1 секунду.

Ниже приведены две функции кеширования для set и get.

Ниже приведен метод получения данных из базы данных.

Приведенный ниже код имитирует 10 одновременных запросов на промах кеша.

Результатом приведенного выше кода будет

total calls made to cache 20. total calls to db 10

Это, конечно, то, на что мы не надеялись. На самом деле, в этом случае это оказалось хуже, чем помещать кеш перед ним, поскольку мы делаем 20 дополнительных вызовов кеша!

Это называется забастовкой кеша.

Решения

Решение 1:

Одно из возможных решений этой проблемы - у нас никогда не бывает промахов в кэше. Есть несколько способов добиться этого: например, каждая запись обновляет кеш / обслуживает устаревшие данные из кеша и т. Д.

Вот видео, объясняющее это решение от Udacity

Однако это не всегда возможно. Иногда данные могут быть огромными и не помещаются в кеш. Иногда нецелесообразно обслуживать устаревшие данные, и ваш кеш имеет TTL и т. Д.

Решение 2:

Разве не было бы замечательно, если бы из базы данных извлекался только один запрос, а остальные ожидали записи в кеш? Это позволит избежать скачков базы данных. Вот алгоритм

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

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

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

Позволяет имитировать 10 одновременных запросов на промах кеша с помощью этой новой функции.

Результат будет

total calls made to cache 11. total calls to db 1

Это то, что мы хотели, и избегали лишних обращений к базе данных.

Прочие соображения:

Есть еще несколько вещей, которые следует учитывать при реализации этого решения.

  • Распространенная проблема с распределенными блокировками заключается в том, что от самой распределенной блокировки можно отказаться. Как система должна с этим справиться?
  • Сколько раз функция должна отклоняться перед вызовом базы данных независимо от блокировки?
  • Можно также выбрать XFETCH, который представляет собой оптимальное вероятностное предотвращение паники кеша. Конечно, для этого есть и пакет npm.
    Послушайте этот разговор о том, как archive.org столкнулся с проблемой забастовки кеша и как они решили эту проблему с помощью xfetch.

Связанные истории





Инкапсулирует компоненты с помощью Bit, чтобы запускать их в любом месте в ваших проектах и ​​приложениях.

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

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

"УЧИТЬ БОЛЬШЕ"