This media is not supported in your browser
VIEW IN TELEGRAM
Платформа с реальными DevOps-задачами. Кейсы по Linux, Docker и Kubernetes — всё как в бою, но с читами:
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👏1
🔬 Правильный вопрос про AI
Все исследования AI-ассистентов меряют одно: насколько быстрее ты закрываешь задачу. Метрика удобная, но она игнорирует 70–80% реальных затрат — поддержку, рефакторинг, устранение дефектов.
Исследование «Echoes of AI» (arXiv, 2025) спросило другое:
«Что будет, когда другой разработчик возьмёт AI-код и попытается его развивать?»
151 участник, 95% практикующие разработчики (не студенты). Java/Spring Boot проект, две фазы, настоящее РКИ. Одна группа пишет с AI, другая без. Потом третья группа без AI поддерживает и тот, и другой код.
Результат оказался неожиданный.
👉 Читать
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava
Все исследования AI-ассистентов меряют одно: насколько быстрее ты закрываешь задачу. Метрика удобная, но она игнорирует 70–80% реальных затрат — поддержку, рефакторинг, устранение дефектов.
Исследование «Echoes of AI» (arXiv, 2025) спросило другое:
«Что будет, когда другой разработчик возьмёт AI-код и попытается его развивать?»
151 участник, 95% практикующие разработчики (не студенты). Java/Spring Boot проект, две фазы, настоящее РКИ. Одна группа пишет с AI, другая без. Потом третья группа без AI поддерживает и тот, и другой код.
Результат оказался неожиданный.
👉 Читать
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁25👍3❤2💯1
Forwarded from Библиотека задач по Java | тесты, код, задания
В каком порядке выполнятся операции при создании Spring-бина?
Anonymous Quiz
32%
Constructor → @Autowired → @PostConstruct → InitializingBean.afterPropertiesSet()
23%
@Autowired → Constructor → @PostConstruct → InitializingBean.afterPropertiesSet()
28%
Constructor → @PostConstruct → @Autowired → InitializingBean.afterPropertiesSet()
8%
@PostConstruct → Constructor → @Autowired → InitializingBean.afterPropertiesSet()
9%
Посмотреть ответ
👍5🔥3❤2👏1
🧩 Просто о сложном: Saga Pattern
Когда пользователь оформляет заказ, нужно списать деньги, зарезервировать товар и уведомить склад. Всё в разных сервисах. Что делать, если один из них упал?
Обычная транзакция тут не поможет. Добро пожаловать в Saga.
Идея проста: разбиваем большую распределённую транзакцию на цепочку маленьких локальных. Каждый шаг — это своя транзакция в своём сервисе. Если что-то пошло не так, то запускаем компенсирующие транзакции в обратном порядке.
🔹 Два подхода
1. Choreography (хореография)
Сервисы общаются через события. Каждый сам знает, что делать дальше.
✔️ Просто, нет единой точки отказа
❌ Сложно отследить весь флоу, спагетти из событий
2. Orchestration (оркестрация)
Есть дирижёр — Saga Orchestrator. Он знает весь сценарий и командует сервисами.
✔️ Флоу виден в одном месте, легко дебажить
❌ Оркестратор может стать узким местом
⚠️ Важно понимать: компенсирующая транзакция ≠ откат БД. Это бизнес-операция. Если деньги уже списаны, то мы не откатываем строку в БД, мы делаем возврат.
В Java-экосистеме Saga используют вместе с:
→ Apache Kafka / RabbitMQ — для событий между сервисами
→ Axon Framework — встроенная поддержка Saga из коробки
→ Spring State Machine — для управления состоянием оркестратора
→ Temporal / Conductor — оркестрация workflow на уровне инфраструктуры
🔹 Когда использовать
✔️ Микросервисная архитектура
✔️ Несколько БД, нет возможности использовать 2PC
✔️ Долгоживущие бизнес-транзакции
❌ Монолит с одной БД — просто используй @Transactional
Saga — это не серебряная пуля, это компромисс. Ты жертвуешь изоляцией ради масштабируемости. Данные могут быть временно не консистентны и это нормально, если бизнес с этим согласен.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#CoreJava
Когда пользователь оформляет заказ, нужно списать деньги, зарезервировать товар и уведомить склад. Всё в разных сервисах. Что делать, если один из них упал?
Обычная транзакция тут не поможет. Добро пожаловать в Saga.
Идея проста: разбиваем большую распределённую транзакцию на цепочку маленьких локальных. Каждый шаг — это своя транзакция в своём сервисе. Если что-то пошло не так, то запускаем компенсирующие транзакции в обратном порядке.
🔹 Два подхода
1. Choreography (хореография)
Сервисы общаются через события. Каждый сам знает, что делать дальше.
OrderService → [OrderCreated] → PaymentService
PaymentService → [PaymentDone] → InventoryService
InventoryService → [Reserved] → NotificationService
2. Orchestration (оркестрация)
Есть дирижёр — Saga Orchestrator. Он знает весь сценарий и командует сервисами.
public class OrderSagaOrchestrator {
public void execute(Order order) {
try {
paymentService.charge(order);
inventoryService.reserve(order);
notificationService.notify(order);
} catch (PaymentException e) {
// компенсация не нужна — деньги не списаны
} catch (InventoryException e) {
paymentService.refund(order); // компенсируем
}
}
}В Java-экосистеме Saga используют вместе с:
→ Apache Kafka / RabbitMQ — для событий между сервисами
→ Axon Framework — встроенная поддержка Saga из коробки
→ Spring State Machine — для управления состоянием оркестратора
→ Temporal / Conductor — оркестрация workflow на уровне инфраструктуры
🔹 Когда использовать
Saga — это не серебряная пуля, это компромисс. Ты жертвуешь изоляцией ради масштабируемости. Данные могут быть временно не консистентны и это нормально, если бизнес с этим согласен.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤2🔥2👏1👾1
Enterprise AI: когда MVP уже не прокатит
В корпоративном секторе требования к AI жёстче: безопасность, стабильность, работа с документами. Мы обновили курс «Разработка AI-агентов», добавив модули, критически важные для Enterprise-разработки.
Java-инженерам будет интересно:
🔹 Advanced RAG. Работа со сложной корпоративной документацией (сканы, таблицы), улучшение поиска и безопасности данных.
🔹 Legal Tech. Как внедрять агентов с соблюдением 152-ФЗ и юридических норм.
🔹 Надёжность. Внедрение
🔹 Legacy. Управление браузером и старыми интерфейсами через агентов.
Стартуй сейчас! Покупаешь курс — сразу получаешь материалы.
🎟 ПромокодAgent — скидка 10 000 ₽ (до 28 февраля).
👉 AI для Enterprise-задач
В корпоративном секторе требования к AI жёстче: безопасность, стабильность, работа с документами. Мы обновили курс «Разработка AI-агентов», добавив модули, критически важные для Enterprise-разработки.
Java-инженерам будет интересно:
🔹 Advanced RAG. Работа со сложной корпоративной документацией (сканы, таблицы), улучшение поиска и безопасности данных.
🔹 Legal Tech. Как внедрять агентов с соблюдением 152-ФЗ и юридических норм.
🔹 Надёжность. Внедрение
Human-in-the-loop для контроля, логирование, трассировка и предотвращение регрессий.🔹 Legacy. Управление браузером и старыми интерфейсами через агентов.
Стартуй сейчас! Покупаешь курс — сразу получаешь материалы.
🎟 Промокод
👉 AI для Enterprise-задач
Java-разработчик — Офис (Казань)
Java-разработчик — от 230 000 до 330 000 ₽ — удалёнка/гибрид (Москва)
Senior Java Developer (Kotlin) — от 400 000 ₽ — удалёнка
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1🔥1
Наглядная шпаргалка с примерами и визуализацией SQL JOIN.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤6⚡2🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
😁37👍6🔥4
ИИ-агенты в Enterprise: как подружить LLM и суровый продакшн
Интегрировать нейросеть в корпоративный бэкенд на Java — это не просто дёрнуть API. Бизнес требует предсказуемости, отказоустойчивости и строгих лимитов. Агенты не должны ложиться от кривых данных или сливать бюджет на бесконечные ретраи.
Мы полностью обновили курс по разработке AI-агентов. Теперь фокус на enterprise-подходе: логирование, трассировка, изоляция доменов и предсказуемое поведение систем.
Что в инженерном фокусе нового потока:
— промышленный RAG: извлечение данных из legacy-баз, сканов и сложных таблиц;
— архитектура агентов: внедрение human-in-the-loop для аппрува критичных транзакций;
— ресурсоёмкость: жёсткий контроль кэша, токенов и переключение режимов обработки;
— интеграции: учим агентов взаимодействовать с легаси-интерфейсами и браузерами;
— комплаенс: развёртывание решений с полным соблюдением 152-ФЗ.
Используйте промокод
Выбирайте акцию «3 курса по цене 1», чтобы забрать два дополнительных курса в подарок.
Внедрить AI в Enterprise
Интегрировать нейросеть в корпоративный бэкенд на Java — это не просто дёрнуть API. Бизнес требует предсказуемости, отказоустойчивости и строгих лимитов. Агенты не должны ложиться от кривых данных или сливать бюджет на бесконечные ретраи.
Мы полностью обновили курс по разработке AI-агентов. Теперь фокус на enterprise-подходе: логирование, трассировка, изоляция доменов и предсказуемое поведение систем.
Что в инженерном фокусе нового потока:
— промышленный RAG: извлечение данных из legacy-баз, сканов и сложных таблиц;
— архитектура агентов: внедрение human-in-the-loop для аппрува критичных транзакций;
— ресурсоёмкость: жёсткий контроль кэша, токенов и переключение режимов обработки;
— интеграции: учим агентов взаимодействовать с легаси-интерфейсами и браузерами;
— комплаенс: развёртывание решений с полным соблюдением 152-ФЗ.
Используйте промокод
Agent до 28 февраля, чтобы получить скидку 10 000 рублей.Выбирайте акцию «3 курса по цене 1», чтобы забрать два дополнительных курса в подарок.
Внедрить AI в Enterprise
Мне НЕ нужно разбираться с управлением памятью в Java, так как за меня всё делает GC
Garbage Collector (GC) действительно очищает неиспользуемые объекты, которые больше не имеют активных ссылок. Благодаря этому в Java не нужно вручную освобождать память, как в C++.
Несколько предпосылок к исходному тезису:
🔹 В других языках, где ручное управление памятью (C, C++), утечки очевидны — если забыл free(), память навсегда потеряна.
🔹 В Java GC работает автоматически, поэтому кажется, что он решает все проблемы сам.
🔹 "Ну раз GC есть, значит, про память можно не думать!" — типичная ошибка.
GC удаляет только те объекты, которые больше не имеют активных ссылок. Если же объект остаётся доступным, но фактически не используется, он будет занимать память до завершения работы приложения.
Если создать static List и постоянно добавлять в него объекты, они никогда не будут удалены GC, потому что статические поля живут весь срок жизни приложения.
public class MemoryLeak {
private static final List<byte[]> cache = new ArrayList<>();
public static void main(String[] args) {
while (true) {
cache.add(new byte[10 * 1024 * 1024]);
System.out.println("Добавили 10MB в кеш. Используемая память: " +
(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024) + "MB");
}
}
}Через пару минут — OutOfMemoryError
Объекты, хранящиеся в ThreadLocal, привязываются к потоку, а в пуле потоков они могут жить дольше, чем нужно.
public class ThreadLocalLeak {
private static final ThreadLocal<byte[]> threadLocalData = new ThreadLocal<>();
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
threadLocalData.set(new byte[10 * 1024 * 1024]); // 10MB на поток
System.out.println("Память занята потоком!");
});
}
executor.shutdown();
}
}Поток завершится, а память останется занята, потому что ThreadLocal не очищается автоматически.
Если анонимный класс или лямбда-ссылка ссылается на внешний объект, она может мешать GC очистить его.
public class InnerClassLeak {
private String data = "Очень важные данные";
public void createAnonymousClass() {
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Используем: " + data);
}
};
new Thread(task).start();
}
}task ссылается на data, даже если InnerClassLeak больше не используется → GC не очистит объект.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤5🔥3
Forwarded from Библиотека собеса по Java | вопросы с собеседований
Задача из реального интервью в Google 👇
📦 Задание
Google хочет проанализировать самые популярные категории поиска для оптимизации результатов.
Таблицы на картинке. Напишите запрос для подсчета общего количества поисков в каждой категории по месяцам за 2024 год.
Ставьте → 🔥, если нравится формат. Если нет → 🤔
#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15❤1👍1
☕ AI-агенты в Enterprise: от прототипов на коленке к надёжным JVM-системам
Для Java-разработчика важна стабильность и предсказуемость. В новом курсе по AI-агентам мы учим строить системы, которые не «галлюцинируют» в продакшене, а работают по строгим инженерным метрикам и соблюдают законы РФ.
📚 В обновлённой программе:
— управляемый инжиниринг: трассировка ошибок, логирование и контроль производительности;
— правовое поле: развёртывание AI-решений с учётом
—
— продвинутый
Доступ к вводным материалам открывается сразу после покупки — начните погружение в архитектуру агентов 2026 года.
⏳ Специальные условия до 28 февраля:
— введите промокод
— участвуйте в **акции «3 курса по цене 1» — выберите два любых курса в дополнение к основному.
👉 Получить доступ к курсу и подаркам
Для Java-разработчика важна стабильность и предсказуемость. В новом курсе по AI-агентам мы учим строить системы, которые не «галлюцинируют» в продакшене, а работают по строгим инженерным метрикам и соблюдают законы РФ.
📚 В обновлённой программе:
— управляемый инжиниринг: трассировка ошибок, логирование и контроль производительности;
— правовое поле: развёртывание AI-решений с учётом
152-ФЗ и всей документации;—
LangGraph промышленного уровня: интеграция human-in-the-loop в бизнес-процессы;— продвинутый
RAG: работа с корпоративными данными, таблицами и сканами.Доступ к вводным материалам открывается сразу после покупки — начните погружение в архитектуру агентов 2026 года.
⏳ Специальные условия до 28 февраля:
— введите промокод
Agent для получения скидки 10 000 рублей**; — участвуйте в **акции «3 курса по цене 1» — выберите два любых курса в дополнение к основному.
👉 Получить доступ к курсу и подаркам
This media is not supported in your browser
VIEW IN TELEGRAM
Прямо в браузере можно посмотреть, что происходит под капотом кода: как создаются и взаимодействуют объекты, как данные перемещаются в памяти, и как работает стек вызовов. Всё это можно увидеть пошагово.
Если что-то непонятно, встроенный AI-помощник объяснит логику кода или поможет разобраться в чужом решении.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3❤1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁28👍3🔥1
🐳 Магия Docker CLI
Забываете, сколько места занимают контейнеры, образы и тома Docker? Не хотите каждый раз лезть в df или гадать? Просто запустите
🔹 Зачем это нужно
— Показывает сколько места занимают образы, контейнеры, тома и билд-кэш.
— Видно реальный размер и сколько можно освободить прямо сейчас.
— Незаменимо, когда диск неожиданно кончается на проде или CI/CD агенте.
🔹 Как использовать
— Краткая сводка: docker system df
— Подробный разбор по каждому объекту: docker system df -v
— Можно комбинировать с docker system prune, чтобы сразу почистить лишнее.
— Удобно добавить в cron или мониторинг, чтобы отслеживать рост потребления.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Забываете, сколько места занимают контейнеры, образы и тома Docker? Не хотите каждый раз лезть в df или гадать? Просто запустите
docker system df, и у вас будет вся картина перед глазами.🔹 Зачем это нужно
— Показывает сколько места занимают образы, контейнеры, тома и билд-кэш.
— Видно реальный размер и сколько можно освободить прямо сейчас.
— Незаменимо, когда диск неожиданно кончается на проде или CI/CD агенте.
🔹 Как использовать
— Краткая сводка: docker system df
— Подробный разбор по каждому объекту: docker system df -v
— Можно комбинировать с docker system prune, чтобы сразу почистить лишнее.
— Удобно добавить в cron или мониторинг, чтобы отслеживать рост потребления.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥2❤1
Если один запрос зависает, batch встаёт колом. Простое увеличение
max.poll.records не решит проблему, если медленные ответы — это постоянное явление.В статье описывается, как заменить пакетную синхронизацию на трёхэтапную модель: подготовка, обработка, постобработка – через специальный wait-топик. Коммит офсета происходит сразу, сохраняя гарантию at-least-once, и даже 8-часовая недоступность Postgres не сорвёт обработку.
В итоге получили 46 TPS против 170 TPS с теми же настройками. Код, конфиги Kafka Connect и результаты тестов прилагаются.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2🔥1
Если производительность внезапно падает, хотя два потока работают с разными частями одного объекта, скорее всего, проблема в так называемом false sharing.
Вот как это работает: процессор не берет данные из памяти побайтово. Он работает с cache line, обычно это 64 байта. Если два ядра процессора держат одну и ту же cache line в своих кэшах первого уровня (L1) и хотя бы одно ядро в нее пишет, запускается протокол когерентности (MESI). Этот протокол делает копию cache line недействительной в другом ядре. И это происходит, даже если ядра пишут в разные поля объекта, но эти поля физически находятся в одной cache line.
🔹 Как объекты лежат в памяти
JVM (HotSpot) раскладывает объект примерно так:
[mark word — 8 байт]
[klass pointer — 4/8 байт]
[поля по убыванию размера: long/double → int/float → short/char → byte/boolean → ссылки]
[padding до выравнивания на 8 байт]
Порядок полей в исходнике не соответствует порядку в памяти. JVM перегруппировывает их для минимизации выравнивания. Проверить реальный layout можно через JOL:
javaSystem.out.println(ClassLayout.parseClass(MyClass.class).toPrintable());
Для класса с `long`, `int` и `boolean` JOL покажет что-то вроде:
OFFSET SIZE TYPE
0 4 (object header: mark)
4 4 (object header: mark)
8 4 (object header: class)
12 4 int value
16 8 long counter
24 1 boolean flag
25 7 (alignment/padding)
Итого 32 байта — меньше cache line. Два таких объекта рядом в массиве легко попадут в одну линию.
🔹 Классический сценарий
class Counters {
volatile long a;
volatile long b;
}Поля a и b занимают по 8 байт. Заголовок объекта – примерно 12-16 байт. Вероятно, оба поля попадают в одну 64-байтную строку кэша. Если два потока независимо увеличивают a и b, они постоянно будут делать строку недействительной друг для друга. На многоядерной системе это легко может привести к падению производительности в 5-10 раз по сравнению с независимыми счетчиками.
Решение – добавление отступов (padding). До Java 8 это делали руками, добавляя фиктивные поля:
class PaddedCounter {
volatile long value;
long p1, p2, p3, p4, p5, p6, p7; // 56 байт padding
}Уродливо и ненадёжно. Плюс JIT мог выкинуть «мёртвые» поля.
С Java 8 появилась аннотация @Contended (пакет jdk.internal.vm.annotation):
@Contended
volatile long a;
@Contended
volatile long b;
В JVM автоматически добавляется padding в 128 байт вокруг помеченного поля. Это сделано для защиты от prefetcher'а (размер двойной cache line). Чтобы это работало вне классов JDK, нужно использовать опцию -XX:-RestrictContended.
Аннотация @Contended стоит на полях внутри Thread (например, для thread-local random), ForkJoinPool и Striped64, который является базовым классом для LongAdder и LongAccumulator.
🔹 LongAdder как способ решения проблемы
LongAdder показывает, как можно решить проблему не просто добавлением отступов, а с помощью особого подхода к проектированию. Вместо одного volatile long используется массив Cell[], где у каждой ячейки стоит @Contended. Каждый поток пишет в свою ячейку, итоговое значение получается через sum(). При большой нагрузке это работает намного быстрее, чем AtomicLong.
За это приходится платить: sum() не является атомарной операцией. Если нужна полная точность в момент чтения, LongAdder не подойдет.
🔹 О массивах примитивных типов
Тут есть свои нюансы с long[]. Элементы располагаются один за другим, без каких-либо дополнительных данных между ними. Восемь элементов long занимают ровно одну cache line. Если несколько потоков одновременно пишут в соседние ячейки, false sharing практически гарантирован. Именно поэтому в Striped64 используется массив объектов Cell[], а не long[]: каждый объект с @Contended изолирован от других.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥6❤4👏1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁22👍5🌚2🔥1
Сайт с интерактивными задачами → CodingBat Java
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
😁9👍6🔥2
🔧 Caffeine: локальный кеш когда Redis избыточен
Для кеширования результатов тяжёлых вычислений или редко меняющихся справочников Redis часто избыточен. Caffeine — высокопроизводительный in-process кеш с Window TinyLFU eviction policy.
🔹 Решение
▪️ Зависимость
▪️ Конфигурация через Spring Cache
▪️ Программная конфигурация с разными политиками
▪️ Метрики через Micrometer
Даёт метрики: cache.gets, cache.puts, cache.evictions, cache.hits, hit rate.
refreshAfterWrite — ключевая настройка для production. В отличие от expireAfterWrite, он не удаляет запись по истечении TTL, а помечает её для фонового обновления. Следующий запрос получит устаревшее значение мгновенно, пока фоновый поток обновляет кеш. Латентность не растёт при рефреше.
⚠️ Caffeine — in-process кеш. При горизонтальном масштабировании каждый инстанс имеет свой кеш. Инвалидация при изменении данных требует либо короткого TTL, либо внешнего механизма (Redis pub/sub, Kafka event). Для справочников с редкими изменениями короткого TTL обычно достаточно.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise
Для кеширования результатов тяжёлых вычислений или редко меняющихся справочников Redis часто избыточен. Caffeine — высокопроизводительный in-process кеш с Window TinyLFU eviction policy.
🔹 Решение
▪️ Зависимость
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
▪️ Конфигурация через Spring Cache
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=1000,expireAfterWrite=10m
cache:
cache-names:
- currencies
- countryDictionary
- featureFlags
▪️ Программная конфигурация с разными политиками
@Configuration
@EnableCaching
public class CaffeineConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager manager = new CaffeineCacheManager();
manager.setCacheLoader(caffeineCacheLoader());
// разные настройки для разных кешей
manager.registerCustomCache("currencies",
buildCache(500, Duration.ofHours(1)));
manager.registerCustomCache("featureFlags",
buildCache(100, Duration.ofMinutes(5)));
// дефолт для остальных
manager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats()); // метрики
return manager;
}
private Cache<Object, Object> buildCache(int size, Duration ttl) {
return Caffeine.newBuilder()
.maximumSize(size)
.expireAfterWrite(ttl)
.refreshAfterWrite(ttl.dividedBy(2)) // фоновое обновление
.recordStats()
.build();
}
}
▪️ Метрики через Micrometer
@Bean
public CacheMetricsRegistrar cacheMetricsRegistrar(MeterRegistry registry,
CacheManager cacheManager) {
return new CacheMetricsRegistrar(registry, List.of(cacheManager));
}
Даёт метрики: cache.gets, cache.puts, cache.evictions, cache.hits, hit rate.
refreshAfterWrite — ключевая настройка для production. В отличие от expireAfterWrite, он не удаляет запись по истечении TTL, а помечает её для фонового обновления. Следующий запрос получит устаревшее значение мгновенно, пока фоновый поток обновляет кеш. Латентность не растёт при рефреше.
══════ Навигация ══════
Вакансии • Задачи • Собесы
#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3🔥1