Кэширование

Кэш – это кратковременная память, которая имеет меньшие объемы, чем долгосрочная, но более высокую скорость доступа. Данный механизм базируется на предположении, что данные, запрошенные однажды будут запрошены еще раз. Кэши используются на различных уровнях:
– Веб-браузер
– Операционная система
– “Железо”
– Веб-приложение и т.д.
В контексте распределенных систем кэш, чаще всего, располагается на более высоком уровне, без избыточного погружения на более низкие слои.

Кэш приложения

В данном случае кэш располагается на уровне приложения. При получении запроса данных, сервер сначала попробует найти их в локальном кэше. Если их там нет, данные будут запрошены из общей памяти и записаны в кэш для последующих запросов.
Данный подход становится куда менее эффективным в случае, когда мы масштабируем наше приложение горизонтально. Потому что каждый инстанс приложения будет работать со своим собственным кэшем приложения. А при повторяющихся запросах балансировщик нагрузки может перенаправить запрос на другой инстанс, который не имеет этих данных в своем локальном кэше.
В этом случае решением могут быть распределенные и глобальные системы кэширования.
Распределенный кэш – состоит из нескольких узлов, каждый из которых хранит определенную часть данных. И если запрошенных данных нет на текущем узле – они будут запрошены на другом. Основным преимуществом распределенных кэшей является легкость горизонтального масштабирования.
Distributed cache

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

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

Инвалидация кэша

Существует 2 основные проблемы программирования: именование переменных и инвалидация кэша. Помимо преимуществ, концепция кэширования ставит перед нами задачу поддерживать его согласованность с основным хранилищем данных. Т.е. если в реляционной БД данные были изменены – мы должны в определенный момент времени уведомить об этом кэш.
Для решения этой задачи существует 3 основных подхода:

  • Сквозное кэширование
    В данном случае данные записываются в кэш и основное хранилище данных одновременно.
    Преимущества данного подхода – это быстрое получение, безопасность и полная согласованность данных.
    Недостатки – высокая нагрузка на кэш.
  • Обходное кэширование
    В этом случае данные записываются в основное хранилище “в обход” кэша. И записываются в кэш только при получении запроса на эти данные. Преимущества – более низкая нагрузка на кэш.
    Недостатки – более высокая задержка при получении новых данных.
  • Отложенное кэширование
    При использовании данного подхода данные записываются только в кэш, а запись в основное хранилище данных происходит, обычно, через заранее определенные временные интервалы.
    Преимущества – высокая скорость записи данных
    Недостатки – риск потери данных в случае аварийного завершения работы приложения до записи данных в основное хранилище

Вытеснение кэша

Так как объем кэша часто ограничен (в сравнении с объемом данных, которые обрабатывает система), необходимо убирать данные из кэша, т.е. вытеснять их.
Существует ряд подходов к вытеснению:

  • Наименее недавно использованный (Least Recently Used – LRU)
    Первым удаляется элемент, который был использован большее количество времени назад от текущего момента
  • Наиболее недавно использованный (Most Recently Used – MRU)
    Удаляется элемент, который был запрошен наименьшее количество времени от текущего момента
  • Первый на вход – первый на выход (First In First Out – FIFO)
    Удаляется элемент, который был записан раньше по порядку, независимо от частоты использования
  • Последний на вход – первый на выход (Last In First Out – LIFO)
    Удаляется элемент, который был записан позже всех по порядку, независимо от частоты использования
  • Случайная замена (Random Replacement – RR)
    Удаляется случайный элемент