Данные и базы

4 мин чтения·Опубликовано ·Обновлено

Кэширование: почему ускорение системы создаёт новую проблему — устаревшие данные

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

«Давайте добавим кэш» звучит как небольшая техническая доработка. Повторный запрос получит готовый ответ, база будет меньше работать, страница откроется быстрее. Но после изменения цены поддержке придётся объяснять, почему в каталоге одна сумма, а при оформлении другая. Этот разговор тоже входит в стоимость ускорения.

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

Сначала найти дорогую работу

Возьмём каталог. Описание популярного товара читают многократно, меняют редко. Здесь повторное использование ответа имеет понятный смысл. А персональный отчёт, который каждый сотрудник строит с новым набором фильтров, может почти не повторяться. Сохранять все результаты окажется дороже, чем кажется по демонстрации одного удачного запроса.

До внедрения нужны исходные измерения: сколько занимает запрос, какая часть времени уходит в базу, как часто повторяются одинаковые обращения. Заодно стоит проверить индекс и сам запрос. Исправить тяжёлое чтение иногда проще, чем годами обслуживать ещё одну копию его результата.

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

Цена и фотография товара стареют по-разному

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

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

Отдельно рассматриваются права доступа. После блокировки сотрудника старый ответ «доступ разрешён» опаснее старой картинки. У такого решения должен быть свой срок действия и механизм отзыва; переносить на него настройки кэша каталога нельзя.

Почему «удаляем через минуту» недостаточно

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

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

В описании Cache-Aside отдельно отмечено, что этот подход сам по себе не гарантирует согласованность кэша и источника. Для критичной операции недостаточно обещания «кэш регулярно очищается»: нужен проверяемый предел устаревания и поведение при его нарушении.

Когда кэш исчезает, нагрузка возвращается

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

Команда может объединять одновременные запросы за одним результатом, заранее прогревать самые востребованные данные, разносить моменты истечения записей и ограничивать число обращений к источнику. Иногда допустимо ненадолго показать старое значение, пока обновляется новое. Но для заблокированного доступа или подтверждения платежа такой запасной вариант требует совсем других правил.

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

Чужой ответ не должен стать общим

Если итоговая цена зависит от клиента, валюты или договора, ключ кэша должен учитывать существенные для ответа различия. Иначе одна компания может увидеть условия другой. Проверка прав остаётся обязательной: правильно составленный ключ не заменяет авторизацию.

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