Skip to content

Кэширование

Работал с кэшированием на нескольких уровнях:

  • HTTP / браузерный кэш;
  • серверный application cache;
  • Redis как backend для cache и lock-механизмов;
  • build-time кэширование;
  • локальный in-memory cache на frontend;
  • кэширование идемпотентных и условно-повторяемых запросов.

Серверное кэширование

Есть опыт прикладного кэширования данных и готовых ответов на уровне backend.

Что использовал на практике:

  • кэширование JSON-ответов в Redis;
  • revision-based invalidation;
  • ETag и условные запросы;
  • выборочное кэширование публичных и пользовательских списков;
  • разделение payload cache и revision key;
  • инвалидацию кэша при изменении данных.

Использовал revision-based схему для Redis JSON response cache:

  • публичные списки кэшируются с ETag и 304 Not Modified;
  • пользовательские списки тоже имеют отдельную схему кэширования;
  • при изменении данных ревизия увеличивается, и старый кэш становится неактуальным без грубой очистки всего store.

HTTP caching: ETag и conditional requests

Реализовывал HTTP Conditional Requests для API и файловых ответов.

Что обычно настраивал:

  • ETag;
  • Cache-Control;
  • 304 Not Modified при совпадении условия;
  • разделение публичного и приватного кэширования;
  • безопасное поведение для изменяемых и чувствительных данных.

На практике это использовалось, например:

  • для index/list endpoint-ов с условной отдачей данных;
  • для списка сохранённых пользователем сущностей;
  • для файловых/изображений endpoint-ов с ETag и cache headers.

Revision-based invalidation

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

Подход, который использовал:

  • отдельный revision key для группы данных;
  • payload cache keys в Redis, завязанные на текущую ревизию;
  • bump revision при изменении данных;
  • прикладные invalidator-классы и команды для управления инвалидацией.

Использовал отдельные invalidator-реализации и artisan-команду для bump revision у публичного списка рецептов.

Redis как cache backend и distributed locks

Использовал Redis как инфраструктурный backend для cache-механизмов.

Что обычно использовал:

  • хранение кэша;
  • lock-механизмы;
  • временные ключи с TTL;
  • служебные данные для антидублей и координации конкурентных запросов.

Redis может участвовать в двух разных ролях:

  • инфраструктурный state: sessions, queues, rate limiter, locks и idempotency/replay keys;
  • ручной HTTP-cache: revision-based payload cache для отдельных GET endpoint-ов вроде списков рецептов и сохранённых рецептов.

Idempotency и replay cache

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

Это выражается через idempotency middleware, которое:

  • строит cache key по idempotency key + запросу + identity;
  • хранит успешный ответ в Redis;
  • возвращает cached replay для повторного запроса;
  • использует lock и in-progress markers, чтобы не допускать конкурентную повторную обработку одной и той же операции.

Кэширование статики и ассетов

Есть опыт настройки кэширования на уровне web-server и фронтенд-ассетов.

Что использовал:

  • точечный fastcgi_cache для публичных GET endpoint-ов;
  • Cache-Control для статических ресурсов;
  • immutable для versioned/hash-named build-ассетов;
  • X-Cache-Status для диагностики web-server cache;
  • раздельные правила для динамики и статики;
  • более короткие или строгие правила для изменяемого контента.

На практике это включало точечный fastcgi_cache для публичного GET /api/v1/timezones, кэширование ассетов /build и отдельные cache headers для изображений.

Build-time cache

Есть опыт использования build/runtime cache-механизмов фреймворка и инфраструктуры.

Из практики:

  • config:cache;
  • route:cache;
  • view:cache;
  • подготовка production-конфигурации с уже прогретыми/собранными артефактами.

Frontend caching

Есть опыт клиентского кэширования на frontend-стороне.

Что использовал:

  • in-memory GET cache в API-клиенте;
  • локальное хранение уже загруженного состояния в store/service-слое;
  • принудительное обновление данных (force reload) при необходимости;
  • cache-busting для отдельных запросов и ресурсов;
  • preload сценарии для изображений и часто используемых данных.

Из практики:

  • in-memory cache в API client для GET-запросов;
  • cache-aware store/service-логике;
  • отдельным возможностям отключать кэш на уровне конкретного запроса.

См. также

Сайт обновлен и проверен: