[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-arkhitektura-prilozheniy-kakie-strategii-keshirovaniya-sushchestvuyut":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":19,"progress":20,"seo":21},134,"kakie-strategii-keshirovaniya-sushchestvuyut",3,"arkhitektura-prilozheniy","Архитектура приложений","🏗️","Какие стратегии кэширования существуют?","Кэширование -- хранение часто запрашиваемых данных в быстром хранилище для снижения нагрузки на основной источник данных и уменьшения времени отклика. Как шпаргалка, в которую заглядываешь вместо того, чтобы каждый раз открывать учебник.\n\n### 1. Cache-Aside (Lazy Loading)\n\nПриложение само управляет кэшем. При промахе читает из БД и кладёт в кэш.\n\n```\n    Запрос → Есть в кэше?\n              ├── Да  → Вернуть из кэша\n              └── Нет → Прочитать из БД → Записать в кэш → Вернуть\n```\n\n\u003Cdetails>\u003Csummary>Пример кода\u003C\u002Fsummary>\n\n```java\n@Service\npublic class AccountService {\n\n    private final AccountRepository repository;\n    private final RedisTemplate\u003CString, Account> redisTemplate;\n\n    public Account findById(Long id) {\n        String key = \"account:\" + id;\n        Account cached = redisTemplate.opsForValue().get(key);\n        if (cached != null) return cached;\n\n        Account account = repository.findById(id)\n            .orElseThrow(() -> new NotFoundException(id));\n        redisTemplate.opsForValue().set(key, account, Duration.ofMinutes(30));\n        return account;\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\nПлюс: кэшируются только реально запрашиваемые данные. Минус: первый запрос всегда медленный (cache miss); данные могут устаревать до истечения TTL.\n\n### 2. Write-Through\n\nПри записи данные сохраняются одновременно в кэш и в БД.\n\n```\n    Запись → Обновить кэш → Обновить БД → Ответ\n```\n\nПлюс: кэш всегда актуален. Минус: увеличенная задержка записи; кэшируются данные, которые могут никогда не читаться.\n\n### 3. Write-Behind (Write-Back)\n\nДанные записываются в кэш немедленно, а в БД -- асинхронно с задержкой.\n\n```\n    Запись → Обновить кэш → Ответ\n                  │\n                  └── Асинхронно (через N мс) → Обновить БД\n```\n\nПлюс: очень быстрая запись. Минус: риск потери данных при сбое кэша до синхронизации с БД. Этот подход не подходит для финансовых операций, где потеря данных недопустима.\n\n### 4. Read-Through\n\nКэш сам обращается к БД при промахе (в отличие от Cache-Aside, где это делает приложение). Приложение всегда обращается к кэшу и не знает об источнике данных.\n\n### 5. Refresh-Ahead\n\nКэш обновляет данные до истечения TTL, если они часто запрашиваются. Предотвращает cache miss для горячих данных.\n\n### Сравнение стратегий\n\n| Стратегия | Кто читает из БД | Кто пишет в БД | Консистентность | Задержка записи |\n|-----------|------------------|-----------------|-----------------|-----------------|\n| Cache-Aside | Приложение | Приложение | Возможны stale data | Нет (пишет напрямую) |\n| Write-Through | Кэш | Кэш (синхронно) | Высокая | Увеличена |\n| Write-Behind | Кэш | Кэш (асинхронно) | Возможна потеря | Минимальная |\n| Read-Through | Кэш | Приложение | Возможны stale data | Нет |\n| Refresh-Ahead | Кэш (проактивно) | Приложение | Высокая для hot data | Нет |\n\n### Инструменты кэширования в Java\n\n| Инструмент | Тип | Применение |\n|------------|-----|-----------|\n| Redis | Распределённый | Кэш между микросервисами, сессии, лимиты |\n| EhCache | Локальный (in-process) | Кэш внутри одного приложения |\n| Caffeine | Локальный (in-process) | Быстрый кэш в памяти JVM, рекомендуется для новых проектов |\n| Hazelcast | Распределённый | Distributed cache, in-memory data grid |\n\n### Использование Spring Cache\n\nSpring предоставляет абстракцию кэширования через аннотации, скрывая конкретную реализацию:\n\n\u003Cdetails>\u003Csummary>Пример кода\u003C\u002Fsummary>\n\n```java\n@Service\npublic class ClientService {\n\n    @Cacheable(value = \"clients\", key = \"#id\")\n    public ClientDto findById(Long id) {\n        return clientRepository.findById(id)\n            .map(ClientMapper::toDto)\n            .orElseThrow();\n    }\n\n    @CacheEvict(value = \"clients\", key = \"#id\")\n    public void updateClient(Long id, UpdateClientRequest request) {\n        \u002F\u002F обновление клиента в БД\n    }\n\n    @CacheEvict(value = \"clients\", allEntries = true)\n    public void clearCache() { }\n}\n```\n\n\u003C\u002Fdetails>\n\n### Типичные проблемы кэширования\n\n- **Cache Stampede** (thundering herd) -- множество одновременных запросов при промахе кэша, все идут в БД. Решение: блокировка (mutex) при подгрузке или вероятностное раннее обновление.\n- **Stale data** -- устаревшие данные. Решение: TTL, активная инвалидация при обновлении.\n- **Cache Invalidation** -- одна из двух самых сложных проблем в computer science (Phil Karlton). Особенно сложна в распределённых системах с несколькими инстансами приложения.\n\n> **На собеседовании:** Интервьюер хочет услышать не просто перечисление стратегий, а понимание trade-off каждой. Частая ошибка -- не упоминать проблемы инвалидации и Cache Stampede.","","middle",[15,16,17,18],"performance","caching","redis","architecture",[],null,{"title":22,"description":23,"ogTitle":22,"ogDescription":24,"keywords":25,"schemaAnswer":34,"featuredSnippetReady":35},"Стратегии кэширования: Cache-Aside, Write-Through, Write-Behind — Gymterview","Какие стратегии кэширования существуют? Cache-Aside, Write-Through, Write-Behind, Read-Through, Refresh-Ahead. Инструменты: Redis, Caffeine, EhCache. Примеры на Spring.","Обзор стратегий кэширования в Java-приложениях: Cache-Aside, Write-Through, Write-Behind с примерами на Spring и Redis.",[26,27,28,29,30,31,32,33],"стратегии кэширования","cache-aside","write-through","write-behind","Redis","Caffeine","Spring Cache","кэширование Java","Основные стратегии кэширования: Cache-Aside (приложение само управляет кэшем, при промахе читает из БД), Write-Through (данные пишутся одновременно в кэш и БД), Write-Behind (данные пишутся в кэш немедленно, в БД — асинхронно), Read-Through (кэш сам обращается к БД при промахе) и Refresh-Ahead (кэш обновляет данные до истечения TTL). В Java-экосистеме используются Redis, EhCache, Caffeine и Hazelcast. Ключевые проблемы — Cache Stampede, устаревшие данные и сложность инвалидации кэша.",true]