Maxim Korobov — DevBlog


Channel's geo and language: Russia, Russian
Category: Technologies


Мой путь в IT/Саморазвитии
по вопросам: @mkorobovv

Related channels

Channel's geo and language
Russia, Russian
Statistics
Posts filter


Forward from: RWB Тех


дроп


Давно не писал в канал. Сейчас я в процессе написания нового контента, а пока предлагаю угадать в комментариях, на какую тему будет новый пост👇


Задумывались ли вы когда-нибудь об эффективности UUIDv4?

Часто при выборе уникального ключа для записи разработчики предпочитают UUIDv4.

Из преимуществ:
1. Глобальная уникальность ID
2. Нет необходимости хранить состояние
3. Быстрая генерация уникального ID

Это важные свойства, если мы работаем с уникальными объектами. Но в один момент эта конструкция ломается.

UUIDs используются как primary key в таблицах, а значит автоматически индексируются.
И вот тут начинаются проблемы. UUIDv4 - это случайные 128 бит. Случайность означает отсутствие локальности данных: новые записи попадают в произвольные места индекса, а не дописываются последовательно в конец, как это происходит с автоинкрементным bigint. Из-за этого при вставке приходится постоянно читать диск.

Как тогда быть, если хочется использовать uuid? Ответ UUIDv7.

UUIDv7 устроен просто: первые 48 бит - это временная метка в миллисекундах, остальная часть также случайна. Из-за этого значения генерируются приблизительно по возрастанию во времени. Это даёт локальность записи «бесплатно»: новые строки физически ложатся рядом друг с другом в индексе. При этом все три исходных преимущества UUID сохраняются.

Также нашел интересную статью, где один разработчик сделал бенчмарк в сравнении разных primary keys на вставку в базу данных где производительность UUIDv7 на 30% выше чем у UUIDv4

https://ardentperf.com/2024/02/03/uuid-benchmark-war/


Немного выпал из жизни канала

Последние месяцы были посвящены дипломной работе, но предзащита уже позади

Остался последний рывок, а вместе с этим постепенно освобождается время на контент


Тестирую Agent Driven Development

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

brainstorming - Клод не просто делает, а задаёт вопросы как разработчик бизнесу.
write-plan - по ответам генерирует .md с планом
execute-plan - по плану запускает субагентов для параллельной разработки

Результат приятно удивил, код сохранил стиль проекта и попал в ожидания, также он написал тесты и самостоятельно прогнал их, при ошибках правил и перезапускал тесты. В некоторых местах, где бизнес-логика была нетривиальная, пришлось немного подправить руками (возможно я передал мало контекста).

Итог, кодить с ИИ можно и нужно, так как разработчики часто тратят очень много времени на рутину, которую ИИ помогает закрыть.

Рекомендация: пропишите ограничения Клоду в ~/.claude/settings.json 🙂


{
"permissions": {
"deny": [
"Read(**/.env*)",
"Read(**/*.pem)",
"Read(**/*.key)",
"Read(**/secrets/**)",
"Read(**/credentials/**)",
"Read(**/.aws/**)",
"Read(**/.ssh/**)",
"Read(**/docker-compose*.yml)",
"Read(**/config/database.yml)",
"Read(secret/**)",
"Read(**/secret/**)"
]
}
}


🌐 [ССЫЛКА НА ПЛАГИН]


Мой сетап для работы в 2026

В эпоху ИИ сложно понять, что реально работает, а что просто хайп. Поэтому делюсь тем, что конкретно мне помогает быть эффективным 👇

💻 Написание кода: VS Code + GoLand + Claude Code

Да-да, я использую две IDE одновременно. В VS Code удобное расширение для клод кода, а написание кода и отладка в GoLand.

🗃 Базы данных: DataGrip

Бесспорный фаворит. Удобная работа с файлами, интеграция с Git. DBeaver тоже неплох, но DataGrip выигрывает по ощущениям.

📝 Заметки: Obsidian + NotebookLM

Тяжело удержать все мысли в голове, поэтому я использую вспомогательные приложения. Obsidian как второй мозг, нужные записи всегда под рукой. NotebookLM для работы с документами: загружаю материалы и быстро достаю нужную информацию через ИИ.

🌐 DevOps: k9s

Терминальный интерфейс для работы с кубером. Мне нравится, что он минималистичный, все работает через hotkeys и клавиатуру.

А чем пользуетесь вы? Какие инструменты открыли для себя?


Transactional Inbox

Пост в продолжение к паттерну Outbox. Outbox гарантирует at-least-once. Но кто гарантирует, что сообщение обработают ровно один раз?

Кажется, достаточно просто обрабатывать сообщения на консьюмере, но тут кроется самая важная проблема - дубли. Двойные списания, двойные записи в БД. Consumer не гарантирует exactly-once. Возможна ошибка коммита, OOM или ретрай.

Какое решение? Использовать Inbox

Суть следующая:

1. Создаем таблицу inbox, где будем хранить idempotency_key
2. При обработке события делаем в одной транзакции вставку в две таблицы: inbox и payments.


INSERT INTO inbox (idempotency_key) VALUES ($1) ON CONFLICT DO NOTHING
-- если inserted = 0, значит дубль — выходим
INSERT INTO payments (order_id, amount, status) VALUES ($1, $2, 'pending')


Важно, что захват ключа и бизнес-операция происходят либо вместе, либо никак.

Итого, exactly-once в распределённых системах - это иллюзия, за которой скрывается at-least-once доставка и идемпотентная обработка на каждом узле.


Agent Skills

Разбирался с возможностями Claude Code. Узнал про скиллы агентов. По сути длинный промпт, который агент вызывает автоматически (или по команде) в нужный момент.

Что есть интересного?

Cкиллов можно создать сколько угодно. Агент сам решает, когда вызывать тот или иной, но можно и форсировать вызов вручную (об этом отдельно).

Нашёл применение для себя: написал скилл для ревью кода и diff'ов в MR/PR. Теперь не нужно каждый раз писать промпт вручную. Ревью всегда проходит по одному шаблону, формат ответа предсказуемый. Заодно добавил в references выжимку из Google Go Style Guide, и Claude обращается к ней при каждом ревью.

Как начать?

Создаем папку


mkdir -p ~/.claude/skills/code-review

Создаем следующую структуру:


.
├── references
│ └── go-style-guide.md
└── SKILL.md

Берем .md файлы отсюда.

Запустить ревью можно через вызов скилла в терминале клода.


/code-review

Сам недавно начал погружаться в агентные системы и интересно, кто ещё как использует их в жизни.


Ну чтож, время разобрать задачку с собеса одного из РФ БигТехов 🟠

К счастью, на этот раз без душных алгоритмов, довольно прикладная задача. Суть следующая:


Есть N экземпляров одного микросервиса. Нужно реализовать Balancer, который:
- отправляет запрос на наименее нагруженный бэкенд
- блокирует бэкенд на 1 час, если за последние 10 минут он вернул 100+ ошибок


бэкенд из себя представляет обыкновенный интерфейс


type Backend interface {
Invoke(ctx context.Context, req Request) (Response, error)
}


структура балансера, которую надо заполнить


type Balancer struct {
// Your code
}


Необходимо реализовать метод балансера:


func (b *Balancer) Invoke(ctx context.Context, req Request) (resp Response, err error) {
// Your code
return resp, nil
}


Своим решением поделюсь в комментариях, но оставлю скрытую ошибку (может не одну) 👀
Пишите в комментариях, сколько ошибок нашли - потом подведём итоги


Как я построил личного RAG-ассистента.

Наконец-то добрался до изучения новой для себя темы.

В последнее время мне хотелось решить довольно простую проблему: заметок в Obsidian становится всё больше, а находить в них нужную информацию вручную всё дольше.

Я не люблю писать пет-проект ради пет-проекта, поэтому я захотел сделать что-то прикладное.

В итоге я решил совместить приятное с полезным и написал своего RAG-ассистента для Obsidian. Он индексирует весь мой vault в векторную БД, на каждый вопрос поднимает релевантные фрагменты заметок и отвечает на основе моего собственного контекста.

Зачем вообще всё это?

Если вы следите за AI-инструментами, то наверняка видели NotebookLM. По сути, мой проект решает похожую задачу , только здесь я сам контролирую весь процесс: от индексации заметок до выбора модели. Для ответов можно использовать как сильные LLM по API, так и open-source модели от Hugging Face.

🔗 Проект можно посмотреть на гитхабе: [GITHUB]


Как я потерял сообщения из Kafka

Однажды на работе столкнулся с неприятным багом - часть сообщений просто не доезжала до сервиса.

Написал consumer с commit после обработки сообщений, казалось, всё ок. Но часть сообщений до сервиса не доезжала. Источник работает по at-least-once, в Kafka сообщения точно попадали.

Начал разбираться, как оказалось, по дефолту в Kafka включён автокоммит:


enable.auto.commit=true # Включить автокоммит
auto.commit.interval.ms=5000 # Автокоммит раз в 5 секунд


Какая здесь проблема?

1. Consumer получил пачку сообщений
2. Kafka автоматически закоммитила offset
3. Посередине обработки случился OOM или Deploy сервиса
4. После рестарта consumer начал читать с уже закоммиченного offset
5. Часть сообщений исчезла навсегда

По итогу отключил автокоммит через enable.auto.commit=false и сообщения перестали теряться.


ah shit, here we go again


Video is unavailable for watching
Show in Telegram
Проблема Dual Write или как не терять данные в микросервисах

Частый вопрос на собеседованиях и классическая ловушка для новичков.

Представим сервис заказов: нужно обновить статус в БД и отправить событие в брокер (Kafka/RabbitMQ). Если делать это по очереди, мы рискуем: запись в БД пройдет, а брокер упадет. Данные разошлись, система в неконсистентном состоянии. Объединить их в одну транзакцию нельзя т.к. разные системы.

Решение - паттерн Transactional Outbox:
1. В одной транзакции обновляем заказ и записываем событие в таблицу outbox в той же БД.
2. Гарантируется ACID. Либо сохранятся обе записи, либо ни одной.
3. Отдельный процесс читает таблицу outbox и перекладывает сообщения в брокер.

Плюсы:
✅ Гарантированная доставка «At-least-once».
✅ Не нужны 2PC.
✅ Сервис не зависит от доступности брокера в моменте.

Минусы:
⚠️Риск дублей: если процесс упадет после отправки, но до пометки «доставлено». Решается идемпотентным консьюмером.

Сделал анимацию, как это работает на деле. Как вам такой формат?


Forward from: RWB Тех
⭐️⭐️ В высоконагруженных системах сотни сервисов общаются друг с другом каждую секунду, и любой простой напрямую влияет на бизнес. Когда latency внезапно вырастает в 5 раз, а алерт приходит среди ночи — хочется не гадать, а точно понимать, что произошло и почему.

Максим Коробов, Go-разработчик, в новой статье на Хабре рассказывает: 

⏹️Чем monitoring отличается от observability — и почему Prometheus ≠ решение всех проблем;
⏹️USE, RED и 4 Golden Signals — что реально работает в продуктовых командах;
⏹️Как правильно считать latency (и почему среднее значение вас обманывает);
⏹️Как настроить трейсинг через OpenTelemetry и увидеть полный execution path запроса;
⏹️Какие ошибки чаще всего убивают observability (кардинальность метрик, избыточные трейсы, перегруженные хранилища)

В статье — практическая реализация на Go: Prometheus, Grafana, OpenTelemetry, slog, реальные примеры кода и запросов в PromQL.

➡️ Читать на Хабре


готовы к дропу?


Как выжать максимум скорости из БД? 🚀

Ситуация, наши данные хранятся в кластере с несколькими хостами и мы хотим получить максимально быстрый ответ, индексы и SQL-оптимизации уже сделали, но все еще не то, что надо.

Hedged Requests

Вместо ожидания одного конкретного узла, мы отправляем запрос сразу на все реплики параллельно. Кто первый прислал ответ тот и победил. Остальные запросы отменяются.

Как это выглядит на практике?

1. Создадим n независимых горутин на каждый хост
2. Используем общий контекст. Как только первый воркер вернул результат отменяем работу остальных.
3. Результат пишем в буферизированный канал и забираем первый пришедший.

Какие минусы у подхода?

• Нагрузка: Потребление CPU и сетевого трафика растет пропорционально количеству реплик.
• Ложные ошибки: Если у ближайшего хоста отвалилась сеть, он ответит быстрее всех с ошибкой, хотя другие хосты могли дать верный ответ.

Возможное Решение: Игнорировать НЕ бизнес ошибки, ждать ответа остальных хостов.

🔗 [ССЫЛКА НА КОД С РЕАЛИЗАЦИЕЙ]


📚 Я нашел лучший способ для обучения. Пошаговый гайд.

Последний месяц я тестирую связку двух инструментов от Google, которая стала для меня настоящим открытием. Делюсь гайдом.

📔 Первый этап: NotebookLM

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

Что я делаю на этом этапе?

Загружаю туда разные ресурсы на конкретную тему (книги, статьи, ссылки).
В результате NotebookLM считывает весь контекст и отвечает, ссылаясь на прикрпленные ресурсы. Из крутых фич могу отметить составление визуальных карт по топикам, что очень помогает разложить большую тему на подтемы.

💎 Второй этап: Gemini Gems

В Gemini есть функция Gems. Простыми словами это создание кастомного ассистента под конкретную задачу.

Что я делаю на этом этапе?

Создаю новый Gem. Прописываю системный промпт (как Gemini должен себя вести). И самое классное - в Gemini можно встроить NotebookLM с уже подготовленной базой знаний.

На выходе получаю личного ИИ-ассистента, который отвечает на вопросы, опираясь только на проверенные мною материалы. NotebookLM может даже сам подбирать источники, но тут я советую все же фильтровать их вручную для лучшего качества. Базу знаний можно всегда пополнять. Сейчас я пробую включать инструмент Guided Learning и прошу ИИ устраивать мне полноценное собеседование по теме после её изучения. Такое сразу приводит в тонус и подсвечивает пробелы. Тут главное быть честным с собой и не гуглить.


🛠 Автоматизация деплоя в Github Actions

В продолжение предыдущего поста, делюсь своим рабочим workflow. Этот конфиг сэкономил мне кучу времени на сборку, тесты и деплой моих пет проектов на бою.

👀 Что внутри?

1️⃣ Linter - перед билдом запускается обязательная джоба с линтером.
2️⃣ Tests - если линтер прошел, то запускаются тесты из репозитория.
3️⃣ Build and Push - собираем Docker-образ и пушим его в Container Registry.
4️⃣ Deploy - Триггерим Dokploy через Webhook, и он сам подтягивает свежий образ и запускает у себя на сервере.

🔗 [ССЫЛКА НА КОНФИГ]


Как я открыл деплой без боли моих проектов ⚙️

Недавно я решил изучить вопрос деплоя моих пет проектов на VPS. Изначально это выглядело просто ужасно. Приходилось писать копоуз на сервере, потом git pull и в конце docker compose up -d. Мне показалось это жутко неудобным, так как при добавлении нового пет проекта приходилось бы проделывать ту же процедуру, а если что-то упало, то узнаю об этом последним.

И вот я наткнулся на Dokploy. Возможно вы слышали про про PaaS типо Vercel, Heroku, которые помогают по магической кнопке развернуть ваше приложение. Так вот Dokploy это open-source решение, который ставится прямо на VPS.

Почему это удобно? 🤔

Под капотом Docker Swarm, легкое масштабирование и управление нодами, сборка через Nixpacks прямо на сервере или готовые образы в Container Registry. Traefik, который сам выпускает SSL-сертификаты и балансирует нагрузку.

Также я настроил CI/CD в Github Actions: теперь сборка и обновление происходят автоматически и без даунтайма.

20 last posts shown.

61

subscribers
Channel statistics
Popular in the channel