TGViewer
Channel Public Channel
Мастерская IT-решений

Мастерская IT-решений

@solutionstudio

О проектировании систем и их взаимодействии. Теория и практические кейсы
Subscribers
161
Photos
45
Videos
2
Links
30

Showing posts older than #102 · Back to latest

Older Posts 18 shown
Post #101 82
Немного о пагинации

Часто ли вы задумываетесь о пагинации при проектировании API? Честно говоря, я не задумывалась. Просто шла по накатанной (limitFrom, limitSize) и все. В кулуарах одной из конференций об этом зашел разговор, и я поняла, что у меня есть пробелы. А теперь делюсь с вами тем, что накопала по этому вопросу.
Оказалось, пагинация затрагивает архитектуру, производительность, UX и бизнес-логику.

Первый и главный вопрос: какую пагинацию использовать? Здесь есть два основных конкурента и один гибридный вариант.

🌖 На основе смещения (Классика)

📿 Как работает: limitFrom, limitSize (как я писала выше)

➕ Плюсы:
- Проста для понимания и реализации.
- Позволяет пользователю прыгать на произвольную страницу (например, с 1 на 10)

➖ Минусы:
- Низкая производительность на больших смещениях: Запрос в базу со смещением 10000 и размером 20 заставит БД пройтись по 10020 записям, прежде чем вернуть 20. Это считается "тяжелым" запросом.
- Если между запросами в набор данных добавились или удалились записи, страницы "поплывут". Пользователь может увидеть дубли или пропустить записи (если запись с предыдущей страницы сместилась вперед).

🔧 Когда использовать?
Для небольших, относительно статичных наборов данных, где важна возможность произвольного перехода по страницам, а производительность не критична.

🌖 На основе курсора

📿 Как работает: Вместо номера страницы используется указатель на конкретную запись. Обычно это уникальный, последовательно возрастающий столбец (например, id, created_at).

➕ Плюсы:
- Производителен, тк запрос использует индекс по курсорному полю и очень эффективен, даже для глубоких страниц.
- Устойчив к изменениям данных. Пользователь видит снимок данных на момент первого запроса (в рамках одной сессии).

➖ Минусы
- Нельзя прыгнуть на страницу 10, не пройдя предыдущие 9. Только "Вперед/Назад".
- Сложнее в реализации, потому что требует передачи курсора на клиент и правильной обработки на бэкенде.
– Курсор жестко привязан к конкретному порядку сортировки. Если нужно сортировать по разным полям, нужны разные курсоры.

🔧 Когда использовать?
Для больших, часто обновляемых наборов данных, где важны производительность и консистентность (ленты социальных сетей, бесконечный скролл, ленты транзакций).


🌖 Keyset
Разновидность курсорной. Более продвинутая форма, где курсором может быть составной ключ (например, (date, id)), что позволяет эффективно работать со сложными сортировками.

В следующий раз разберем критерии, по которым можно выбирать подход
Post #100 114
Ну очень приглянулось 😅
Весёлых вам праздников!
  • ❤ 3
Post #99 83
Хочу поделиться с вами статьей, тема которой сегодня волнует, я думаю, многих.

Что с ИТ-рынком?
Дефицит кадров? Перенасыщение? Что делать и куда бежать?
https://habr.com/ru/companies/ddosguard/articles/960606/

Статья холиварная (особенно в комментах).

От себя добавлю: в целом согласна с мнением редакции, но есть пара пунктов....

Работа для айтишника не может закончиться
Может. Для тех кто работает на создание ПО. Кто на поддержке, у того ситуация стабильнее.

В январе 2025 «Бизнес FM» стращал массовыми сокращениями в IT-отрасли (в реальности, если судить по приведенной Минцифры статистике, произошло прямо противоположное)
Противоположное? Серьёзно? На конференциях осеннего сезона я активно собираю статистику этого аспекта. И ещё никто не сказал мне "сокращения в моей компании? Не, не слышал..."

Мне интересно, что вы скажете. Что думаете о рынке? Что задело в статье? Что планируете делать дальше?
Делитесь!))
Post #98 84
Правильный вариант:
3️⃣ (Без кеширования), с оговоркой на вариант 2️⃣ для некоторых данных.

Объяснение
🟩 Почему вариант 3️⃣ — основной: Для строго консистентных данных, где критична абсолютная актуальность (например, текущий баланс), кеширование опасно. Пользователь может увидеть устаревшие данные и, например, совершить платеж, думая, что у него есть деньги. Любой TTL > 0 создает риск расхождения.

🟥 Почему не вариант 1️⃣ (Приложение): 30 секунд — это огромное окно неконсистентности для финансовых данных. Стратегия абсолютно неприемлема в контексте финансов.

🟧 Оговорка про вариант 2️⃣ (БД): Для истории операций, которая только добавляется, но не удаляется, можно использовать чтение с реплик (это форма кеширования). Пользователь может не заметить отставание в пару секунд, а нагрузка на основную базу снизится. Но для баланса это недопустимо.

Вывод: не все данные можно и нужно кешировать. Консистентность и актуальность иногда важнее производительности.
Post #97 68
❗️Новая задачка! Потренируемся?

В личном кабинете банка пользователь должен видеть актуальный баланс своего счета и историю операций. Любое отставание или несоответствие данных недопустимо.

Варианты решения:

1️⃣ Кеш на уровне приложения: Кешировать баланс пользователя в Redis на 30 секунд для снижения пиковой нагрузки на систему.

2️⃣ Кеш на уровне БД: Настроить репликацию базы данных и читать историю операций с реплики, которая может отставать на несколько секунд.

3️⃣ Без кеширования: Не использовать кеш для этих данных вообще. Все запросы отправлять непосредственно в основную базу данных.

Кидайте свои варианты в комментарии. Разбирать будем вечером
Post #96 79
Правильный вариант:
2️⃣
(Кеш на уровне приложения).

Разбираем почему так.

• Почему НЕ вариант 1 (БД)
Кеш на уровне БД снимет нагрузку с движка базы, но не уменьшит количество самих запросов к ней. Он также негибкий — при изменении одного профиля инвалидировать кеш сложно.

• Почему НЕ вариант 3 (Клиент)
Данные профиля персональны и могут меняться. Если закешировать их в браузере на час, пользователь может не сразу увидеть свои обновления или изменения на странице друга. Кроме того, этот кеш не снимет нагрузку с серверной части.

• Почему вариант 2 (Приложение)
Это идеальный компромисс.
– Расположение: Кеш в Redis расположен близко к приложению, снимает нагрузку с базы данных и drastically уменьшает количество запросов к ней.
– Стратегия вытеснения: LRU отлично подходит для соцсети, так как вытесняет профили наименее активных пользователей, оставляя в кеше "горячие" данные.
– Время жизни (TTL): 5 минут — разумный баланс между актуальностью данных (изменения станут видны в течение 5 минут) и эффективностью кеша.

Совпало?
будем делать еще задачку?
Post #95 70
Хотите несколько практических задач?
Такой опрос я проводила на одном из докладов, попробуем в онлайне такое провести. Здесь и задачи усложнились, и времени на подумать будет больше.

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

Варианты ответов

1️⃣ Кеш на уровне БД: Использовать встроенный кеш запросов базы данных. Время жизни — 10 минут.

2️⃣ Кеш на уровне приложения: Разместить в памяти приложения (например, с помощью Redis) объект "Профиль пользователя". Использовать стратегию LRU (Least Recently Used) и время жизни (TTL) 5 минут.

3️⃣ Кеш на уровне клиента: Отправлять заголовки HTTP-кеширования браузеру пользователя со временем жизни 1 час.

Пишите в комментарии свой вариант.
Ответ будем разбирать вечером.
  • 🔥 3
Post #94 75
На что обратить внимание при внедрении кеша

🔛 Несогласованность данных
Самая частая проблема. Вы кешируете данные, они меняются в источнике, а в кеше остаются старые.
Решение: Грамотная стратегия инвалидации (TTL или по событию).

🔛 "Стартовый шторм" При перезапуске кеш пуст. Все запросы обрушиваются на базу данных и могут "положить" ее.
Решение: Предварительный "прогрев" кеша или использование постоянного хранилища для кеша.

🔛 Несанкционированное прокникновение
Запросы по несуществующим ключам (например, user_id=-1) постоянно пролетают мимо кеша и бьют по БД. Решение: Кешировать сам факт отсутствия данных (например, положить null с коротким TTL).

🔛 Разрушение кеша
Одновременная инвалидация очень популярного ключа (например, по истечению TTL), что приводит к лавине запросов в БД для его пересчета.
Решение: Использование механизма "блокировки" (mutex), чтобы только один поток пересчитывал значение, а остальные ждали.

🔛 Проблема "горячего" ключа
Один ключ (например, данные супер-популярного товара) получает огромное количество запросов, создавая нагрузку на один узел распределенного кеша.
Решение: Репликация "горячего" ключа на несколько узлов или его дублирование в локальном L1-кеше приложения.


❓ С чего начать при внедрении кеша?
Небольшой план действий для начинающего кошатника 🐱 КЕШатника:
1. Измерьте и найдите самое медленное место.
2. Выберите тип кеша, который поможет в решении этой проблемы.
3. Внедрите простую стратегию (например, Cache-Aside с TTL).
4. Продумайте инвалидацию.
5. Мониторьте эффективность (количество попаданий и промахов кеша) и будьте готовы к подводным камням.

Часто самый большой выигрыш дает кеширование на уровне веб-сервера (Nginx) для статики и HTML и использование Cache-Aside паттерна с Redis/Memcached для данных приложения.
  • ❤ 1
  • 👏 1
Post #93 87
Виды кеширования и когда их выбирать

По расположению (архитектурный уровень)

🔹 Клиентское кеширование
Как работает: Браузер или мобильное приложение хранит статику (CSS, JS, картинки) и даже данные (via LocalStorage).
Когда использовать: Для снижения нагрузки на сервер и ускорения отклика для конечного пользователя. Рекомендуется использовать HTTP-заголовки Cache-Control, ETag.

🔹 Кеширование на прокси (CDN)
Как работает: Сеть доставки контента (Cloudflare, AWS CloudFront) кеширует статический и даже динамический контент на своих edge-серверах по всему миру.
Когда использовать: Для раздачи статики (изображения, видео) и динамического контента глобальной аудитории. Снижает задержку.

🔹 Веб-сервер / Кеш обратного прокси
Как работает: Nginx, Varnish кешируют целые HTML-страницы или API-ответы перед приложением.
Когда использовать: Для разгрузки backend-серверов. Идеально для страниц, которые одинаковы для многих пользователей (блог, новостная лента).

🔹 Кеширование приложения (In-Memory)
Как работает: Приложение хранит данные в своей оперативной памяти (например, HashMap в Java, dict в Python) или использует распределенный кеш (Redis, Memcached).
Когда использовать: Для кеширования результатов запросов к БД, тяжелых вычислений, сессий пользователей. Самый гибкий вид.

🔹 Кеширование базы данных
Как работает: Сама СУБД имеет внутренний кеш для результатов запросов и индексов.
Когда использовать: Работает "из коробки", но настраивается под конкретную СУБД. На него можно влиять, но основное управление — у базы данных.


По стратегии доступа

🔺Cache-Aside (Lazy Loading)
Как работает
1. Приложение ищет данные в кеше.
2. Если данные в кеше не найдены, берет из БД.
3. Приложение кладет данные в кеш

➕ Простота, отказоустойчивость (при падении кеша система работает напрямую с БД).
➖Возможность пропуска кеша на каждый запрос, риск "стартового шторма" (т.е. когда за каждым запросом обращаемся в базу) после сброса кеша.

Когда использовать
Наиболее распространенный подход. Идеален для читаемой нагрузки с предсказуемыми данными для кеширования.

🔺 Read-Through
Как работает
Приложение всегда читает из кеша. Если данных нет, кеш сам загружает их из БД и возвращает приложению.

➕ Чище архитектура приложения.
➖ Требует от кеша возможности загружать данные (например, Redis Modules).

Когда использовать
Когда логика загрузки данных стандартна и может быть вынесена в слой кеша.

🔺 Write-Through

Как работает
Приложение записывает данные в кеш, а кеш синхронно записывает их в БД.

➕ Гарантирует консистентность между кешем и БД.
➖ Высокая задержка записи.

Когда использовать
Когда консистентность критически важна, а производительность записи — нет.


🔺 Write-Behind (Write-Back)
Как работает
Приложение записывает данные в кеш, который асинхронно (с задержкой) обновляет БД.

➕ Очень высокая производительность записи.
➖ Риск потери данных при сбое кеша, возможна несогласованность.

Когда использовать
Для данных, которые можно временно потерять или где запись очень частая (например, счетчики просмотров, лайки).
Post #92 79
Это ли не прекрасно...?
Post #89 87

Forwarded from ИТ ПСБ

🐈 Наши коллеги едут в Светлогорск — чтобы представить ПСБ на Merge Baltic 2025.

➡️Роман Миловидов и Данила Шалыгин поделятся опытом выстраивания процесса управления потоком продуктовых задач в соответствии с целями бизнес-направления. Ответят на вопросы, как понять предназначение отдела, как использовать рефлексию в системах discovery и delivery, как визуализировать end2end процесс для управления потоком задач.

➡️Дарья Борисова расскажет реальную историю о том, как один аналитик смог создать интеграцию под ключ без командной работы. И обсудит, стоит ли аналитику брать на себя роль разработчика, где проходит грань между экономией бюджета и потерей качества, и каким может быть будущее профессии аналитика.

Merge — крупнейшая профессиональная конференция, где встречаются эксперты из самых разных сфер ИТ: от разработки до маркетинга.
  • 🤩 2
  • 👍 1
Post #88 81
А вот и новость №6
Сегодня вылетаю на Merge Baltic!
Есть здесь те, кто тоже туда едет?
Post #87 88
Как использовать кеширование эффективно

Для удовлетворения нефункциональных требований по производительности, масштабированию, доступности и надежности может участвовать кеширование.
Эффективное кеширование — это не просто "включить Redis". Это стратегия. Разберем процесс по косточкам.

🧲 Что лучше кешировать
– Часто читаемые, редко меняющиеся данные (Каталог товаров, справочники, контент страниц, настройки)
– Результаты тяжелых вычислений (Агрегированная статистика, отчеты, рекомендательные выборки)
– Сессии пользователей

♨️ Что НЕ надо кешировать
– Часто меняющиеся данные (Текущий баланс счета, место водителя такси на карте)
– Чувствительные/персональные данные (если только кеш не надежно зашифрован).
– Уникальные данные, которые вряд ли будут запрошены повторно.

🔑 Стратегия инвалидации
Инвалидация - это обновление кеша. Политика ее выбора - самая сложная часть.
– Time-To-Live (TTL)
Самый простой способ. Устанавливаем время жизни записи в кеше. Подходит для данных, где не будет слишком критично, если данные ненадолго"протухнут" (например, список новостей).
– Инвалидация по событию
или "Write-Through/Write-Behind". При любом изменении данных в источнике нужно обновлять или удалять соответствующие данные в кеше. Этот подход позволяет оставлять данными в наиболее свежем состоянии, но требует сложной логики.
– Отложенная запись
или "Write-Behind". Запись данных сначала происходит в кеш, а затем асинхронно "сбрасывается" в основное хранилище. Повышает производительность записи, но есть риск потери данных при сбое.

📇 Выбор размера кеша и политики вытеснения


Что делать, когда кеш заполнен? Нужно почистить его от лишних данных. Как определить, какие данные являются лишними? Есть специальные политики
- LRU (Least Recently Used) — вытесняются давно неиспользуемые данные (фильтр по дате)
- LFU (Least Frequently Used) — вытесняются реже всего используемые данные (фильтр по частоте обращения)

🟰 Многоуровневое кеширование

– Уровень 1 (L1): Внутрипроцессный кеш (в памяти приложения). Очень быстрый, но не разделяемый между экземплярами приложения.
– Уровень 2 (L2): Внешний кеш (Redis, Memcached). Чуть медленнее из-за сетевого взаимодействия, но разделяемый между всеми экземплярами приложения.

Дальше разберем виды кеширования
Post #86 105
Что делать с системой при разных значениях RPS?

При формировании нефункциональных требований ранее мы упомянули, что из-за невысокого RPS мы можем позволить себе несложную архитектуру. Очень захотелось развить эту тему и порассуждать, при каких RPS влияет на сложность и надежность системы.


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

🌀 Основные уровни значений RPS и рекомендуемые меры

🟢 Низкая нагрузка (< 10 RPS)

Примеры ситуаций: небольшие внутренние сервисы, прототипы, проекты начального этапа разработки.

✨ Подходящие решения:

- Монолитная архитектура
- Локальная база данных
- Минимальные средства мониторинга
- Отказ от кеширования или использование простого кеша (Redis для хранения сессий).

🟠 Средняя нагрузка (~10–100 RPS)

Примеры ситуаций: средние корпоративные веб-приложения, небольшие онлайн-магазины, региональные сервисы.

⚙️ Рекомендуемые шаги:

- Разделение на отдельные модули (Service-Oriented Architecture, SOA);
- Кеширование на уровне сервера приложений (Varnish, Redis, Memcached);
- Оптимизация баз данных (индексация, репликация master-slave);
- Автоматическое масштабирование хостинга (AWS Auto Scaling, Kubernetes HPA).

🔴 Высокая нагрузка (~100–1000 RPS)

Примеры ситуаций: крупные веб-сервисы, корпоративные CRM, большие e-commerce площадки.

🚀 Необходимые меры:

- Микросервисная архитектура (каждый сервис отвечает за свою область);
- Балансировка нагрузки (Nginx, HAProxy, AWS ELB / ALB);
- Горизонтальное масштабирование (масштабирование вычислительных ресурсов в облаке);
- Использование шардирования (разбиение базы данных на части);
- Интеграция CDN (Content Delivery Network) для ускорения доставки статического контента.

🔵 Очень высокая нагрузка (> 1000 RPS)

Примеры ситуаций: глобальные социальные сети, высоконагруженные игровые платформы, финансовые транзакционные системы.

🪄 Какие технологии применять:

- Полностью асинхронная обработка запросов (event-driven architecture, очереди сообщений Kafka, RabbitMQ);
- Распределённые хранилища данных (Cassandra, MongoDB);
- Географически распределённая инфраструктура (multi-datacenter deployment);
- Расширенное кэширование (использование многоуровневых прокси-кешей, Redis Cluster);
- Высокая степень автоматизации деплоев и мониторинг (Kubernetes, Docker Swarm, CI/CD pipeline).


🔝 Общие принципы выбора подхода

- Простота против сложности: Чем ниже RPS, тем проще должно быть решение. Это очевидно, но сказать стоит: избегайте избыточной сложности там, где она не нужна.
- Масштабируемость: Подбирайте инфраструктуру, способную выдержать пиковые нагрузки (особенно сезонные всплески активности пользователей).
- Надёжность: Важнее всего гарантировать доступность сервиса при любом количестве запросов (это не всегда важнее всего. На своих докладах осеннего сезона я подробно разбираю этот аспект).
- Стоимость поддержки: Усложнение инфраструктуры повышает стоимость обслуживания и внедрения новых функций.

📍📍 Итоговая рекомендация

При достижении порога в ~100 RPS целесообразно задуматься о переходе к более сложной инфраструктуре и подготовке среды к росту нагрузки. Однако решающее значение имеет также качество самих запросов: если запросы сложные (например, требуют больших вычислений или объёмных выборок из базы данных), начать подготовку стоит заранее, ещё при меньших значениях RPS.
  • ❤ 1
Post #85 103
Новость №5.

В сентябре вышла моя первая статья на Хабре в блоге ПСБ. Охватить хотелось как можно больше, поэтому она получилась лонг-ридом.

Описала, кажется, все подводные камни, с которыми сталкивалась при проектировании API. Может, найдете что-то для себя!

За 2 недели более 5 тыс прочтений. Для меня это знак, что я создаю актуальные материалы. Пошла работать дальше.

Хотите посмеяться? когда вышла эта статья, по стечению обстоятельств, мое имя появлялось в новостной ленте банка 4 раза по разным поводам, поэтому неделю 22-26 сентября медийка Банка назвали в мою честь (в шутку)

https://habr.com/ru/companies/psb/articles/949246/
  • 🔥 2
Post #84 97
♻️ 5. Удобство использования и Совместимость ♻️

📜 Требования
✏️ UI/UX: Интерфейс должен быть интуитивно понятным для библиотекарей с минимальным обучением. Критичные операции (сканирование штрих-кода книги и читательского билета) должны выполняться с минимальным количеством кликов.
✏️ Кросс-браузерность: Веб-интерфейс должен корректно работать в современных браузерах (Chrome, Firefox, Safari, Edge).
✏️ Мобильность: Адаптивный интерфейс или отдельное мобильное приложение для работы с портативными сканерами штрих-кодов.

📕 Способы исполнения

🗝 Фреймворки: Использование современных frontend-фреймворков (React, Vue.js, Angular)
🗝 User Testing: Проведение тестирования с реальными библиотекарями на ранних этапах на базе прототипов в Figma).



♻️ 6. Тестируемость и Поддерживаемость ♻️

📜 Требования
Код должен быть хорошо документирован и покрыт тестами, чтобы упростить добавление нового функционала и исправление ошибок.

📒 Способы исполнения

📁 Паттерны:
🗳 Модульная архитектура: Следование принципам SOLID и использование Dependency Injection для создания слабосвязанного кода, который легко тестировать.

📁 Инструменты и практики:
🗳 Покрытие кода тестами: Написание модульных (Unit), интеграционных (Integration) и end-to-end (E2E) тестов.
🗳 CI/CD: Настройка автоматизированных пайплайнов (например, в GitLab CI/CD, GitHub Actions) для запуска тестов и развертывания на тестовые/продуктивные среды.
  • ❤ 1
Post #83 92
♻️ 4. Масштабируемость ♻️

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

📗Способы исполнения
📐 Вертикальное масштабирование: Увеличение ресурсов существующего сервера (более мощный CPU, больше RAM). Минусы: имеет физический предел.
📐 Горизонтальное масштабирование: Добавление новых серверов-клонов с приложением за балансировщиком нагрузки. Более современный и гибкий подход. Для этого приложение должно быть stateless (не хранить состояние сессии на сервере, а использовать, например, JWT или хранилище сессий в Redis).


📗 Архитектура
Выбор микросервисной архитектуры (разделение на сервис каталога, сервис выдачи, сервис отчетности) упростит независимое масштабирование отдельных частей системы в будущем. Приведу небольшой спойлер, который мы будем разбирать подробнее в секции архитектуры: для старта работы библиотечной системы монолитная архитектура является более оправданной. А почему - обсудим :)
Post #82 100
♻️ 3. Безопасность ♻️

📜 Требования
✏️ Конфиденциальность: Данные читателей (персональные данные, история чтения) должны быть защищены от несанкционированного доступа.
✏️ Аутентификация и Авторизация: Строгое разграничение прав между библиотекарями (могут выдавать книги) и администраторами (могут управлять пользователями, настраивать систему).
✏️ Аудит: Вести лог всех действий, особенно связанных с изменением данных (изменение размера штрафа, удаление записи о книге, сброс пароля).

📉 Способы исполнения

📓 Паттерны:
RBAC (Role-Based Access Control): Система прав доступа, основанная на ролях. Создаются роли Librarian и Admin, каждой роли назначаются разрешения на конкретные endpoints API или экраны UI.

📓 Инструменты и практики:
〰️ HTTPS: Обязательное использование шифрованного соединения для всего трафика.
〰️ Хэширование паролей: Пароли пользователей (библиотекарей и админов) должны храниться в базе данных только в виде хэшей.
〰️ Валидация входных данных: Защита от SQL-инъекций и XSS-атак путем использования ORM или подготовленных выражений
〰️ JWT (JSON Web Tokens) или OAuth 2.0: Для управления сессиями пользователей после входа в систему.
  • ❤ 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →