Прямой ответ
Согласованность распределённого кэша определяется тем, что источник остаётся единственным местом истины, поэтому расхождение значений кэша устранимо восстановлением из источника.
| Параметр | Что определяет |
|---|---|
| Источник истины | Место, откуда берётся актуальное значение |
| Расхождение | Различие значений между узлами кэша |
| Инвалидация | Способ устранения расхождения |
| Проверка | Подтверждение совпадения кэша и источника |
def invalidate(key: str):
redis.delete(key)
redis.publish("cache:invalidate", key)
Удаление записи из общего кэша и уведомление узлов устраняют расхождение, поэтому следующее чтение получает значение из источника. О стратегиях кэширования — в статье про кэширование данных.
Источник истины и расхождение значений
Источник остаётся единственным местом истины, поэтому значение кэша считается производным и восстанавливаемым.
Источник истины. Актуальное значение хранится в источнике, поэтому кэш содержит копию, пригодную для восстановления.
Расхождение значений. Значение в кэше может отличаться от значения в источнике, поэтому расхождение определяется как допустимое окно либо устраняется инвалидацией.
Восстановление кэша. Кэш восстанавливается чтением из источника, поэтому потеря либо расхождение кэша не приводит к потере данных.
Практическое следствие: кэш, используемый как место хранения единственной копии значения, не восстанавливается после потери, поэтому расхождение становится потерей данных.
Отдельный аспект — локальный кэш узла. Каждый узел может держать собственную копию значения, поэтому инвалидация в общем кэше не затрагивает локальные копии узлов. Уведомление узлов об инвалидации устраняет расхождение локальных копий.
Инвалидация между узлами и окно несогласованности
Инвалидация охватывает все узлы, поэтому значение не остаётся прежним на части узлов после изменения.
Инвалидация общего кэша. Запись удаляется из общего кэша, поэтому чтение любого узла обращается к источнику.
Уведомление узлов. Узлы получают уведомление об инвалидации, поэтому локальные копии удаляются вместе с записью общего кэша.
Окно несогласованности. Период между записью в источник и инвалидацией кэша, поэтому чтение в этом окне возвращает прежнее значение.
Практическое следствие: инвалидация только общего кэша оставляет локальные копии узлов с прежним значением, поэтому часть запросов возвращает устаревшие данные.
Проверка согласованности и поведение при отказе
Согласованность проверяется сравнением значения кэша со значением источника, поэтому расхождение обнаруживается по факту.
Сравнение значений. Значение кэша сравнивается со значением источника, поэтому расхождение обнаруживается явно.
Доля расхождений. Доля значений с расхождением показывает, насколько инвалидация охватывает узлы.
Поведение при отказе кэша. Чтение обращается к источнику, поэтому работа продолжается медленнее, но не отказывает.
Практическое следствие: расхождение, не обнаруженное проверкой, остаётся незамеченным, поэтому пользователь видит прежнее значение без признака проблемы.
О стратегиях инвалидации — в статье про кэш-инвалидацию; о стратегиях распределённого кэширования — в статье про distributed caching.
Практика: настройка согласованности кэша
1. Держите источник единственным местом истины. Значение кэша восстанавливается чтением из источника, поэтому расхождение не приводит к потере данных.
2. Инвалидируйте общий кэш и локальные копии узлов. Значение не остаётся прежним на части узлов после изменения.
3. Уведомляйте узлы об инвалидации. Локальные копии удаляются вместе с записью общего кэша.
4. Сокращайте окно несогласованности. Инвалидация после записи в источник сокращает период возврата прежнего значения.
5. Проверяйте долю расхождений. Доля значений с расхождением показывает, насколько инвалидация охватывает узлы.
6. Проверяйте поведение при отказе кэша. Чтение обращается к источнику, поэтому работа продолжается медленнее.
7. Фиксируйте расхождения в метриках. Рост расхождений указывает на неполный охват инвалидацией.
Рекомендации:
- Не используйте кэш как единственное место хранения значения. Потеря кэша означает потерю данных, поэтому восстановление невозможно.
- Учитывайте локальные копии узлов при инвалидации. Инвалидация только общего кэша оставляет прежние значения на узлах.
- Сопоставляйте окно несогласованности с требованием к актуальности. Запрос, требующий актуальных данных, направляется на источник.
- Фиксируйте долю расхождений в метриках. Рост доли указывает на неполный охват инвалидацией.
- Пересматриваем охват инвалидации при добавлении узлов. Новый узел требует включения в уведомление об инвалидации.
Практический сценарий: часть узлов возвращала прежнее значение
Контекст: после изменения данных часть запросов возвращала актуальное значение, а часть — прежнее, поэтому поведение казалось случайным.
- Диагностика. Проверка показала, что узлы держали локальные копии значений. Инвалидация удаляла запись из общего кэша, но локальные копии узлов не затрагивались, поэтому узел с локальной копией возвращал прежнее значение.
- Причина. Инвалидация не охватывала локальные копии узлов, поэтому расхождение сохранялось на части узлов.
- Действия. (а) Добавили уведомление узлов об инвалидации, чтобы локальные копии удалялись вместе с записью общего кэша; (б) сократили срок жизни локальных копий, чтобы расхождение устранялось даже при потере уведомления; (в) настроили проверку доли расхождений, чтобы охват инвалидацией был измерим; (г) проверили поведение при отказе кэша и убедились в продолжении работы через источник; (д) настроили метрику расхождений, чтобы неполный охват обнаруживался.
- Результат. Все узлы возвращают актуальное значение после изменения, поэтому поведение не зависит от узла.
Вывод: локальные копии узлов сохраняют прежнее значение после инвалидации общего кэша, поэтому часть запросов возвращает устаревшие данные. Уведомление узлов об инвалидации и сокращение срока жизни локальных копий устраняют расхождение между узлами.
FAQ
Что считается источником истины в распределённом кэше? Источник данных, поскольку значение кэша является производной копией и восстанавливается чтением из источника.
Почему часть узлов возвращает прежнее значение? Локальные копии узлов не затрагиваются инвалидацией общего кэша, поэтому расхождение сохраняется на части узлов.
Как устранить расхождение между узлами? Уведомлением узлов об инвалидации и сокращением срока жизни локальных копий. Расхождение устраняется даже при потере уведомления.
Что происходит при отказе кэша? Чтение обращается к источнику, поэтому работа продолжается медленнее. Отказ кэша не должен приводить к отказу приложения.
Источники: Redis optimization, Redis pub/sub, AWS Caching Best Practices — ссылки в шапке.