Стратегия недействительности кеша

В моем текущем приложении мы имеем дело с некоторой информацией, которая редко изменяется.
Для оптимизации производительности мы хотим сохранить их в кеше.
Но проблема заключается в аннулировании этих объектов при каждом их обновлении.
Мы не доработали продукт кэширования.
Поскольку мы создаем это приложение на Azure, мы, вероятно, будем использовать Azure Redis cache.
Одной из стратегий может быть добавление кода в Update API, который сделает недействительным объект в кэше.
Я не уверен, что это чистый путь?
Мы не хотим использовать срок действия кэша, основанный на времени (TTL).
Не могли бы вы предложить некоторые другие стратегии, используемые для аннулирования кэша?

Ответ 1

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

У вас есть два варианта, когда происходит ОБНОВЛЕНИЕ:

  1. Вы можете попытаться установить новое значение во время операции обновления или
  2. Просто удалите старый и обновите во время операции чтения.

Если вам нужен LRU-кеш, тогда UPDATE может просто удалить старое значение, и при первом получении объекта вы создадите его снова после чтения из реальной базы данных. Однако, если вы знаете, что ваш кэш очень мал, и вы используете другую основную базу данных для задач, отличных от размера данных, вы можете обновить непосредственно во время ОБНОВЛЕНИЯ.

Однако всего этого недостаточно, чтобы быть полностью последовательным.
Когда вы пишете в свою БД, кеш Redis может быть недоступен, например, в течение нескольких секунд, поэтому данные между ними не синхронизируются.
Что вы делаете в этом случае?
Есть несколько вариантов, которые вы можете использовать одновременно.

  1. В любом случае установите TTL, чтобы в конечном итоге поврежденные данные обновлялись.
  2. Используйте ленивый читательский ремонт. Когда вы читаете из БД, время от времени проверяйте у основного, соответствует ли значение. Если нет, обновите кэшированный элемент (или удалите его).
  3. Используйте эпохи или аналогичные способы доступа к вашим данным. Не всегда возможно, однако иногда вы получаете доступ к кэшированным данным о данном объекте. Когда это возможно, вы можете изменять идентификатор объекта/дескриптор каждый раз, когда изменяете его, поэтому невозможно получить доступ к устаревшим данным в кэше: каждое имя ключа относится к определенной версии вашего объекта.

Таким образом, del-cache-on-update и write-cache-on-read - это базовая стратегия, но вы можете использовать другие дополнительные системы для устранения несоответствий.

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

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

Ответ 2

Я думаю, что лямбда (ish) архитектура подходит для вашего случая использования.

  1. Обновления в реальном времени для немедленного использования в бизнесе
  2. Пакетная загрузка данных для исправления любых ошибочных записей
  3. Пакетная загрузка данных для удаления любых недействительных/архивных записей.

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

Для пакетной загрузки данных вы можете воспользоваться инструментами приема данных, такими как logstash/fluentd, чтобы "извлечь" последние данные из вашей базы данных. Это можно сделать на основе столбца, который всегда увеличивается (идентификационный номер или timestamp).

У меня есть база данных Oracle на моем конце. Плагин Logstash JDBC отлично справляется с последними записями. Вывод logstash можно отформатировать и распечатать в файл, который может использовать Redis. Я написал небольшой скрипт bash, чтобы организовать это. Проверено на 3 миллиона записей и работает хорошо.

Ответ 3

Помимо TTL (Time To Live, например, удаление ключей по истечении заданного периода времени), обычной стратегией является LRU (Least Recent Used): когда вам нужно удалить некоторые записи (например, когда вы достигнете максимального предела памяти), вы удаляете самые старые записи.

Тем не менее, давно нужно точно знать, какая запись является самой старой, поэтому Redis использует статистический подход, беря несколько записей по умолчанию (3 по умолчанию) и удаляя последнюю используемую).

см. http://redis.io/topics/lru-cache