Максим Добрынин | Как стать востребованным Java разработчиком | ex. Jetbulb

Максим Добрынин | Как стать востребованным Java разработчиком | ex. Jetbulb

@jetbulb

IT community с полезными материалами о программировании, технических собеседованих и рабочих буднях в IT. Авторский контент от @maksymdobrynin

4 929подписчиков
Ежедневно🇷🇺

Похожие каналы

Все →

Последние посты

Максим Добрынин | Как стать востребованным Java разработчиком | ex. Jetbulb — пост в ТГ канале

❓Почему сообщения дублируются при доставке At-least-onceГарантия at-least-once delivery (доставка «как минимум один раз») часто встречается в в качестве решения. На первый взгляд звучит надежно и создается впечатление, что это сообщение точно не потеряется. Но у этой гарантии есть важное следствие — дубликаты неизбежны.Разберёмся, почему это происходит.В основе лежит простая идея: брокер сообщений считает сообщение доставленным только после получения подтверждения (ack) от потребителя. Пока ack не получен, сообщение считается «необработанным» и может быть отправлено повторно.Типичный сценарий дублирования выглядит так:🔹Потребитель получает сообщение🔹Успешно обрабатывает его (например, записывает в базу)🔹Но не успевает отправить ack (или ack теряется)🔹Брокер сообщений считает, что сообщение не обработано🔹И совершает повторную попытку отправкиВ результате одно и то же сообщение обрабатывается дважды.Важно понимать: с точки зрения брокера всё корректно. Он действует по контракту — «лучше отправить ещё раз, чем потерять».➖ Какие существуют причины неполучения ack?🔹сбой сети между консьюмером и брокером сообщений🔹ошибка в консьюмере после обработки, но до отправки ack🔹таймаут обработки (visibility timeout в SQS, session timeout в Kafka)🔹ребалансировкаВот отсюда и происходит природа дупликаторов при различного рода коммуникациях, включая асинхронную.➖ Что с этим делать?Главный подход — идемпотентность. Обработчик должен уметь безопасно обрабатывать одно и то же сообщение несколько раз. На практике это реализуется так:🔹использование уникального ключа для контроля уникальности🔹хранение обработанных запросов в БД🔹обновление вместо вставки в БДНапример, если сообщение создает заказ, перед его созданием будет выполнена проверка на возможность его существования в системе. В случае детекции дубликата, такого сообщение будет игнорироваться и пользователю вернется ответ связанный уже с ранее обработанным сообщением.📌 ВыводПри доставке At-least-once сообщения могут дуб

2 апр. 2026 г.938В Telegram

📚Почему пагинация решение, которое плохо масштабируется“Offset пагинация” — это самый простой и интуитивный способ разбивать данные на страницы. Он часто используется «по умолчанию», потому что легко реализуется и хорошо ложится в модель page/size. Однако на реальных нагрузках и больших объемах данных этот подход начинает деградировать. Вот пример:SELECT * FROM orders ORDER BY created_at DESC LIMIT 10 OFFSET 10000;➖ Проблема производительностиС точки зрения разработчика всё выглядит логично: «пропусти 10 000 записей и верни следующие 10». Но проблема в том, как это операция будет выполнена внутри СУБД. База данных не умеет «перепрыгивать» строки, поскольку не удерживает курсов из предыдущего запроса. Напротив, необходимо пройти через эти 10 000 записей, чтобы определить, какие именно нужно отбросить. Даже при наличии индекса это часто означает сканирование по индексу или таблице с последующим отбрасываем ненужных записей.В результате сложность запроса растет линейно относительно OFFSET. Если первая страница выполняется за миллисекунды, то страница с OFFSET 100000 может уже занимать десятки или сотни миллисекунд. При OFFSET в миллионы — это становится серьезной нагрузкой на ЦПУ и диск. Именно поэтому говорят, что “Offset пагинация” имеет сложность O(n) и плохо масштабируется.➖ Проблема согласованностиЕсть и вторая проблема — согласованность данных. “Offset пагинация” не гарантирует стабильный результат, если данные в таблице меняются между запросами. Например: пользователь открывает первую страницу, затем в систему добавляются новые записи, и при переходе на вторую страницу часть данных может продублироваться или, наоборот, пропасть. Это особенно критично для систем с высокой частотой записи (логирование, события, заказы).Отдельно стоит отметить, что ORDER BY в таких запросах обязателен. Без него СУБД не гарантирует порядок строк, и пагинация становится недетерминированной (одна и та же страница может возвращать разные данные при каждом вызове).📌 РешениеАльтернатив

1 апр. 2026 г.920В Telegram

⚠️Что делать разработчику в текущих реалиях рынка. Все мы видим, что происходит последнее время на рынке. На 1 вакансию разработчика - тысячи отликов за несколько дней. Наступило время, когда рынок стал рынком работодателя. А это значит, что старые правила больше не работают.Раньше было достаточно:🔹 знать стек🔹 писать код🔹 иметь 2–3 года опытаИ можно было спокойно жить и :🔹 менять работу🔹 расти стабильно по зарплате🔹 получать офферыСейчас этого мало. И многие это уже почувствовали:— отклики есть → офферов нет— интервью проходят → финал не дают— опыт есть → роста нетРынок стал значительно жёстче. Компании перестали нанимать “на вырост”.Им нужны люди, которые:— сразу приносят пользу— понимают систему— могут принимать решения⚡️Многие продолжают делать то же самое. Учат новые технологии не покладая рук, проходят курсы “по фреймворкам”, решают задачки чтобы блеснуть умом на собесдеовании. Но это почти не влияет на результат. Потому что проблема не в знаниях.Проблема в уровне мышления.Сейчас работаделям нужен не “ещё один разработчик”, а инженер, который:🔹 понимает архитектуру🔹 умеет декомпозировать систему🔹 видит последствия решений🔹 может объяснить, почему сделал именно так❓Что, собственно, предлагаете делать в такой ситуации? 1️⃣ Перестать думать “что изучить”И начать думать:“какие задачи я умею решать?”Это ключевой сдвиг.2️⃣ Выйти из уровня задач → в уровень системыНе:— “как написать этот сервис”А:— зачем он нужен— как он взаимодействует с другими— где он сломается— как он масштабируется3️⃣ Начать активно лезть в архитектуруДаже если страшно и “пока не мой уровень”.Именно там рост.4️⃣ Искать сложность, а не комфортЕсли ты постоянно делаешь знакомые задачи и не сталкиваешься с неопределённостью - это стагнация. 5️⃣ Прокачивать объяснениеНа интервью решает не только то, что ты знаешь.А то, как ты это доносишь:— структура— логика— аргументация6️⃣ Получать реальный опытЭто самый важный пункт. Пока у тебя нет:— командной разработки— архитектурных решений— сложных

31 мар. 2026 г.903В Telegram

❓Почему знание AtomicInteger не делает тебя сильнееТы можешь знать:• как работает CAS• что такое атомарность• как устроен multithreadingНо на интервью спросят:“Как ты обеспечишь консистентность данных между сервисами?”И это уже не про Java, а про архитектуру.Именно здесь большинство “сильных разработчиков” начинают плавать.🗓 На курсе по микросервисной архитектуре мы как раз разбираем:🔹 как работает консистентность в распределённых системах🔹 какие паттерны реально применяются🔹 как принимать архитектурные решенияСтарт: 6 апреляОсталось 4 места👉 Подробности и запись: https://iprody.com/microservices-java💬 Задать вопрос / забронировать место: https://t.me/iprody_online

30 мар. 2026 г.1 100В Telegram

☕️ AtomicInteger — как работает атомарность без блокировок?На собеседованиях по Java этот вопрос встречается регулярно. И не зря — он отлично проверяет понимание многопоточности. AtomicInteger обеспечивает атомарные операции с помощью CAS (Compare-And-Swap) без использования synchronized и явных блокировок.➖ Как это работает внутри?В основе лежит низкоуровневая инструкция процессора CAS (Compare-And-Swap). Она делает три шага за одну атомарную операцию:🔹Сравнивает текущее значение с ожидаемым🔹Если совпадает, заменяет на новое🔹Если нет, ничего не делаетint prev, next;do { prev = atomicInt.get(); next = prev + 1;} while (!atomicInt.compareAndSet(prev, next));return next;Если другой поток изменил значение между get() и CAS — операция просто повторится.➖ Почему это без блокировок?В таком алгоритме отсутствует Mutex. Потоки не блокируются, а вместо этого они повторяют попытку. Это называется lock-free подход.В итоге, достигается высокая производительность при низкой/средней конкуренции, меньше контекстных переключений, хорошо масштабируется.Однако, при высокой конкуренции возможны частые повторы и есть вероятность возникновения проблемы ABA.📌 ВыводAtomicInteger использует CAS — атомарную инструкцию процессора, которая позволяет обновлять значение без блокировок. Если операция не удалась из-за гонки (Race Condition), она повторяется в цикле.⬇️ А тебе часто задают вопросы о многопоточности на собеседованиях? Пиши о своем опыте в комментариях.👍 Понравился этот пост? Подписывайся, ставь лайк и поделись постом с другом или коллегой.Курс по Kubernetes | Курс по разработке и проектированию микросервисной архитектуры | Групповая практикапо разработке микросервисной архитектуры | Java Roadmap | Задать вопрос менеджеру | Отзывы

30 мар. 2026 г.1 070В Telegram

🔥 Осталось 5 из 15 мест на Курс по проектированию и разработке микросервисной архитектуры 2.0Старт — 6 апреля.Места разбирают очень быстро. Подробнее про курс в постеНовый курс про то, как:— проектировать систему вокруг бизнес-домена (DDD)— строить Event-Driven архитектуру— управлять распределёнными транзакциями (Saga / Outbox)— обеспечивать гарантии доставки сообщений— проектировать отказоустойчивость (Circuit Breaker, Retry, Bulkhead)— строить масштабируемую архитектуру, готовую к росту нагрузки🎯 Кому особенно актуальноЕсли вы:🔹 действующий разработчик🔹 работаете с монолитом или простыми сервисами🔹 чувствуете пробелы в архитектуре🔹 хотите перейти на уровень Middle+ / Senior🔹 готовитесь к сильным компаниям— этот курс даст системность.⬇️ Что будет на выходе— понимание распределённой архитектуры— практическая реализация паттернов— опыт проектирования, а не просто кодинга⌛️ Осталось 5 мест из 15Группа изначально формируется небольшой, чтобы сохранить качество архитектурных разборов и обратной связи.Старт — уже 6 апреля.👉 Подробности и запись: https://iprody.com/microservices-java💬 Задать вопрос / забронировать место: https://t.me/iprody_online

27 мар. 2026 г.1 210В Telegram

📚Testcontainers или как правильно тестировать интеграцию с базой данныхПривет, всем!Макс вещает 😼Одна из частых проблем на любых проектах это тестирование интеграции с базой данных.Обычно встречаются два подхода: использование мокирования (Mock) или In-memory БД (H2 и др.). Оба варианта имеют серьезные ограничения и недостатки.При мокировании, тест не проверяет реальный SQL-запрос, не выявляет ошибки в запросах, не отражает поведение БД, и др. важные детали.При использовании In-memory БД, элементарно выбранная вами СУБД может отличаться от той, которую вы реально будет использовать в продакшене. Например, для тестов вы используете H2, для среды развертывания PostgreSQL. Это может оказать влияние на работу с индексами, может проявиться различие в SQL-диалектах, и само собой – неожиданные ошибки в проде.Это все можно описать одним выражением: Вы эмулируете инфраструктуру, а не запускаете ее.🔹Решением может быть TestcontainersTestcontainers позволяет запускать реальные сервисы в Docker прямо во время тестов.Вместо H2 вы используете настоящую базу данных, которая полностью соответствует вашей инфраструктуре.Пример с PostgreSQL:@Testcontainers@SpringBootTestclass UserRepositoryTest { @Container static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18"); @Autowired UserRepository userRepository; @Test void shouldSaveUser() { User user = new User("test@example.com"); userRepository.save(user); assertTrue(userRepository.findByEmail("test@example.com").isPresent()); }}🔹Что происходит под капотом?Перед выполнением тестовых сценариев будет запущен Docker, затем PostgreSQL container и только потом Spring-приложение подключается к нему. После выполнения теста контейнер удаляется. В данном случае, каждый запуск будет выполняться с чистой базой, что обеспечивает контролируемое управление данными и доступ к ним.🔹Почему это правильно?Testcontainers дает реальное поведение базы, выполняется настоящий SQL-зап

27 мар. 2026 г.1 100В Telegram
Максим Добрынин | Как стать востребованным Java разработчиком | ex. Jetbulb — пост в ТГ канале

☕️ Почему ForkJoinPool быстрее обычных потоков и когда его применятьКогда речь заходит о многопоточности в Java, многие думают о классических потоках (Thread, ExecutorService). Но в задачах с большим количеством мелких операций гораздо эффективнее работает ForkJoinPool.Для того, чтобы разобраться почему это так, сперва необходимо понять в чем проблема обычных потоков.Типичный пример можно представить следующим образом:ExecutorService pool = Executors.newFixedThreadPool(4);Проблемы выражаются в том, что: задачи распределяются статически, один поток может быть перегружен, а другой — простаивать, отсутствует балансировка нагрузки. В результате возможности ЦПУ используется неэффективно.➖ Как работает ForkJoinPool?ForkJoinPool реализует модель Divide → Execute → Merge. Другими словами: задача разбивается на подзадачи (fork), подзадачи выполняются параллельно, затем результаты объединяются (join).Вычисление суммы всех значений очень длинного массива:class SumTask extends RecursiveTask<Integer> { private final int[] arr; private final int start, end; protected Integer compute() { if (end - start <= 10) { int sum = 0; for (int i = start; i < end; i++) { sum += arr[i]; } return sum; } int mid = (start + end) / 2; SumTask left = new SumTask(arr, start, mid); SumTask right = new SumTask(arr, mid, end); left.fork(); int rightResult = right.compute(); int leftResult = left.join(); return leftResult + rightResult; }}Главная причина скорости — алгоритм Work Stealing, который ForkJoinPool использует.Так, у каждого потока есть своя очередь задач, поток берет задачи из своей очереди, а если очередь пуста — "ворует" задачи у других потоков.В отличие от обычного пула, такой алгоритм быстрее, поскольку: нет простаивающих потоков, нагрузка автоматически балансируется, уменьшается конкуренция за ресурсы (contention). В итоге, ЦПУ используется максимально эф

26 мар. 2026 г.962В Telegram
Максим Добрынин | Как стать востребованным Java разработчиком | ex. Jetbulb — пост в ТГ канале

🤚 Освойте Kubernetes за 1,5 месяцаОбъявляем старт набора нового курса по K8SС 2024 года Kubernetes стал де-факто стандартом оркестрации контейнеров.А зарплаты специалистов со знанием Kubernetes в среднем на 18% выше по рынку.Мы сделали курс, который проведёт тебя от Docker до продакшн-кластера:— Мини-группы до 20 человек— Живые занятия 2 раза в неделю с обратной связью от преподавателя— Практика на каждом уроке— Наставник уровня Senior— Полный доступ к записям12 занятий для полного освоения Kubernetes1. Введение в контейнеризацию 2. Основы Kubernetes3. Рабочие нагрузки (Pod, ReplicaSet, Deployment)4. Сетевые ресурсы (Service, ClusterIP/NodePort/LoadBalancer, DNS)5. Балансировка HTTP-запросов при помощи IngressСмотреть полную программуПо результатам курса ты:- освоишь Kubernetes- разработаешь проект для портфолио- получишь опыт CI/CD, мониторинга и логирования- получишь сертификат о прохождении курса и рекомендации по дальнейшему развитию_______________👉🏻 Старт группы - 20 апреляМесто разлетаются очень быстро, успей занять свое 😉Подробная информация на сайте - iprody.com/courses-kubernetesЗадать вопрос/забронировать место - написать менеджеру

25 мар. 2026 г.979В Telegram

📚Liquibase — как обновлять схему базы без простоевОбновление схемы базы данных является одной из самых рискованных операций, особенно в продакшене. Неправильная миграция может привести к падению сервиса или всей системы, нежелательным простоям (downtime), несовместимости схемы с ее клиентами и элементарно к финансовым потерям.Liquibase помогает управлять изменениями схемы, но сам по себе не гарантирует отсутствие простоев. Для этого нужно правильно применять “zero downtime” подход.➖ Как работает LiquibaseLiquibase использует changeset (набор изменений). Каждый changeset: выполняется один раз, фиксируется в таблице DATABASECHANGELOG и не повторяется при следующем запуске.Пример:<changeSet id="1" author="dev"> <addColumn tableName="users"> <column name="age" type="int"/> </addColumn></changeSet>➖ Где возникают проблемы?К типичный сценариям можно отнести добавление новой колонки с ограничением NOT NULL. Старый код не знает о существовании новой колонки, об ограничениях примененных к ней, обязательных данных может еще не быть. В итоге, миграция выполнится, но бизнес-операция провалится.➖ Принцип zero-downtime миграцийГлавное правилом такой миграции является – изменения схемы должны быть совместимыми (forward/backward compatible). Пошаговую стратегию можно описать следующим образом:🔹Добавление изменений без ограничений. Например, добавляем новую колонку без ограничений NOT NULL и DEFAULT.🔹Обновление кода и его развертываниеНапример, в новой версии приложений начинаем использовать новую колонку, а старые версии продолжают читать старые данные. Система работает в режиме совместимости.🔹Миграция данныхЗаполняем колонку данными по-умолчанию. Это можно выполнить батчами, асинхронно и без блокировки таблицы.🔹Полный переход на новую версиюОбновляем код на использование исключительно новой колонки. Старая колонка перестает используется.🔹ОчисткаТеперь можно безопасно удалить старое поле и финализировать миграцию схемы в БД без рисков возникновения отказов или сб

25 мар. 2026 г.935В Telegram