Оконная функция LAG() позволяет получить предыдущее значение в отсортированном наборе. Если order_number - LAG(order_number) > 1, значит есть пропуск между предыдущим и текущим номером. Пример запроса: sql
WITH gaps AS ( SELECT LAG(order_number) OVER (ORDER BY order_number) AS prev_num, order_number AS curr_num FROM orders ) SELECT (prev_num + 1) AS missing_start, (curr_num - 1) AS missing_end FROM gaps WHERE curr_num - prev_num > 1;
Почему другие варианты хуже:
B (LEFT JOIN с таблицей всех чисел) – требует генерации последовательности, что при больших диапазонах неэффективно. C (GROUP BY) – не может найти пропуски без генерации всех значений. D (NOT EXISTS) – потребует для каждого номера подзапрос, что медленно.
Реальный кейс: В интернет-магазине из-за ошибок в интеграции номера заказов иногда пропускались. Аналитик написал запрос с LAG() и за 0.1 секунды нашёл все разрывы в таблице из 10 млн записей.
Вывод:LAG() – оптимальный инструмент для поиска пропусков в последовательностях без генерации вспомогательных таблиц.
И именно поэтому я собрала папку, где уже есть всё необходимое:
— как расти в Telegram — где брать трафик — как превращать подписчиков в деньги — как выстроить систему, а не надеяться на «повезёт» Ссылка: https://t.me/addlist/sieqVFdCuh5iZWIy
Нотация UML: Синхронное сообщение – сплошная стрелка с заполненным треугольником (отправитель ждёт ответа).
Асинхронное сообщение – открытая стрелка (незаполненный треугольник). Отправитель не блокируется. Ответ (callback) изображается отдельным асинхронным сообщением в обратном направлении (или сплошной стрелкой, если это возврат управления).
Реальный пример: Приложение отправляет запрос на оплату в платёжный шлюз и продолжает показывать анимацию. Через некоторое время шлюз присылает результат на webhook – это отдельное асинхронное сообщение.
Ошибка: Если нарисовать синхронную стрелку, подразумевается блокировка, что не соответствует реальности.
Вывод: Аналитик, моделируя интеграции, должен различать синхронные и асинхронные вызовы на диаграммах последовательности.
Почему это реальная проблема? Бизнес-правила, особенно в скоринге или ценообразовании, со временем меняются. Если пороги (50 и 70 баллов) жёстко зашить в код, каждое изменение правила потребует нового релиза, тестирования и развертывания. Это медленно, дорого и рискованно.
Что должен был сделать аналитик: Выделить варьируемые параметры – в данном случае пороги и, возможно, саму шкалу. Требовать, чтобы эти параметры хранились во внешней конфигурации (файл, база данных, административная панель) и могли изменяться без перекомпиляции и передеплоя. Зафиксировать в требованиях механизм динамической настройки – например, «система должна считывать пороги скоринга из таблицы БД при старте и периодически перечитывать их без остановки».
Почему не подходят другие варианты: A (нагрузочное тестирование) – не связано с изменчивостью правил. C (согласование с юристами) – полезно, но не решает проблему частых изменений. D (формальная спецификация) – нужна, но без гибкости всё равно потребуется перекомпиляция.
Реальный кейс: В одном банке кредитные пороги менялись раз в месяц. Они были закодированы в Java-классах. Каждый раз команда делала релиз (2 дня). После перехода на конфигурационный файл с автоматической перезагрузкой изменения стали занимать 10 минут. Что должен зафиксировать аналитик (расширенное требование):
«Пороговые значения для принятия решения по скорингу должны быть вынесены во внешний конфигурационный файл или базу данных. Система должна перечитывать их без перезапуска при изменении. Интервал перечитывания – не более 5 минут. Изменение порогов не должно требовать остановки работы системы».
Дополнительные аспекты: Аудит изменений – кто, когда и почему изменил порог. Валидация новых порогов (например, нижний порог не может быть выше верхнего). Возможность A/B-тестирования разных порогов в разных сегментах клиентов.
Вывод: Аналитик обязан выявлять параметры бизнес-правил, которые могут меняться со временем, и закладывать их во внешнюю конфигурацию. Это ускоряет внесение изменений и снижает стоимость доработок.
Что такое consumer lag (отставание потребителя)? Это разница между смещением последнего сообщения в очереди и смещением, которое уже обработал потребитель. Если сообщения приходят быстрее, чем обрабатываются, очередь растёт, и задержка доставки (латентность) увеличивается. Например, очередь растёт на 100 сообщений в секунду, через час в ней будет 360 000 необработанных сообщений, а новое сообщение будет ждать обработки часы.
Причины consumer lag: Медленная бизнес-логика (тяжёлые запросы в БД, вызовы внешних API). Недостаточное количество потребителей (один consumer на много партиций). Сетевые задержки или блокировки.
Как решить: Увеличить количество параллельных потребителей (в RabbitMQ – добавить экземпляры приложения, слушающие ту же очередь; в Kafka – увеличить число consumer’ов в группе, но не больше числа партиций).
Оптимизировать обработку – асинхронные вызовы, пакетная обработка (batch), распараллеливание внутри потребителя. Использовать flow control – если потребитель не успевает, можно временно приостановить чтение.
Почему не другие варианты: A (retry storm) – это проблема синхронных ретраев, а не медленного потребителя. C (deadlock) – взаимоблокировка, не связано с очередью. D (split brain) – проблема распределённых систем, когда два узла думают, что они лидеры.
Реальный кейс: В системе логистики потребитель Kafka обрабатывал каждое сообщение (заказ) синхронно, вызывая внешний API доставки (среднее время 200 мс). При пике 5000 сообщений/сек очередь начала расти на 2000 сообщений/сек. Увеличили количество партиций с 1 до 10 и запустили 10 потребителей. Потребление выросло в 10 раз, и отставание прекратилось.
Что должен зафиксировать аналитик: В требованиях к интеграции указать допустимый consumer lag (например, не более 10 000 сообщений). Предусмотреть автоматическое масштабирование потребителей (Kubernetes HPA по длине очереди). Мониторинг: алерт, если lag превышает порог.
Вывод: Consumer lag – главная метрика здоровья систем на основе очередей. Аналитик должен закладывать требования к пропускной способности и мониторингу отставания.
В 2000 году профессор Эрик Брюер сформулировал, что в распределённой системе (данные хранятся на нескольких узлах) невозможно одновременно гарантировать все три свойства: Consistency (C) – строгая согласованность: после успешной записи все последующие чтения видят эту запись (нет устаревших данных). Availability (A) – доступность: каждый запрос получает ответ (даже если часть узлов недоступна).
Partition tolerance (P) – устойчивость к сетевым разделениям: система продолжает работать, когда связь между узлами нарушена. При сетевом разделении (например, кабель между дата-центрами оборван) система вынуждена выбирать между C и A. Если выбираем CP (согласованность + устойчивость к разделениям), то при разделении блокируем запись, чтобы не нарушить согласованность. Доступность падает: некоторые запросы не получают ответа. Если выбираем AP (доступность + устойчивость к разделениям), то разрешаем запись в каждый раздел независимо, но потом данные могут расходиться (согласованность нарушена).
Почему пример иллюстрирует CAP? В задаче сказано: система должна быть строго согласованной и доступной. При сетевом разделении она перестаёт принимать запись. Это значит, что система жертвует доступностью для сохранения согласованности. То есть система выбрала CP. CAP-теорема объясняет, почему невозможно иметь и то, и другое одновременно.
Разбор других вариантов: A (теорема Геделя) – о неполноте формальных систем, к распределённым БД не относится. C (закон Амдала) – о максимальном ускорении при распараллеливании, не про согласованность. D (теорема Коуза) – экономическая, о трансакционных издержках.
Реальный пример из практики:
Банковская система (CP) – при разделении между офисами временно запрещает списания, чтобы не возникло отрицательного баланса. Доступность снижена, но деньги в безопасности.
Социальная сеть (AP) – при разделении дата-центров вы всё равно можете поставить лайк (доступность), но счётчик лайков может временно расходиться (eventual consistency).
Что должен зафиксировать аналитик: В требованиях к распределённой системе явно указать, что важнее: строгая согласованность или доступность. Например: «В системе управления запасами товара допустима задержка репликации не более 5 секунд, но запись товара должна быть всегда доступна (AP)» или «Платёжная система должна быть строго согласованной (CP)».
Вывод: CAP-теорема – фундаментальное ограничение, которое аналитик обязан понимать при проектировании распределённых систем. Нельзя попросить «идеальную систему», нужно выбирать компромисс.
Когда сервис A вызывает сервис B через REST API, он ждёт ответа. Если B недоступен (сетевая проблема, падение, перезагрузка), A получает ошибку. Если A не сохранил данные локально, они теряются навсегда. Даже с ретраями (повторными попытками) при длительном сбое (например, 30 минут) данные всё равно потеряются после исчерпания попыток.
Как асинхронная очередь решает проблему Брокер сообщений (RabbitMQ, Kafka, Amazon SQS) действует как надёжный буфер: Сервис A отправляет сообщение в очередь и не ждёт ответа (асинхронно). Если сервис B недоступен, сообщение остаётся в очереди. Очередь хранит сообщения на диске (персистентность), поэтому даже перезапуск брокера не удалит их. Когда B восстанавливается, он забирает все накопившиеся сообщения и обрабатывает их. Гарантируется доставка «хотя бы один раз» (at‑least‑once), а при правильной настройке – идемпотентная обработка.
Почему другие варианты не подходят: A (синхронный REST + ретраи) – ретраи помогают при кратковременных сбоях (секунды), но при длительной недоступности (часы) данные теряются. Кроме того, ретраи могут создать дополнительную нагрузку на восстанавливающийся сервис (эффект «retry storm»). C (периодическая синхронизация) – например, раз в час. За это время данные могут устареть, а при сбое в момент передачи всё равно возможна потеря. Не подходит для интерактивных сценариев. D (общая БД) – антипаттерн в микросервисной архитектуре: сервисы начинают зависеть от схемы данных друг друга, теряется независимость, сложно эволюционировать
Реальный кейс из практики: Сервис заказов интернет-магазина должен был отправлять данные в CRM. Изначально использовали синхронный REST. При падении CRM на 10 минут 200 заказов не попали в CRM, и менеджеры не видели их. После перехода на RabbitMQ заказы публиковались в очередь. При сбое CRM сообщения накапливались в очереди (до 10 000 за час). После восстановления CRM обработала все заказы за несколько минут. Потери данных были исключены.
Что должен зафиксировать аналитик в требованиях: «Взаимодействие между сервисами при не критическом ко времени отклика сценарии должно быть асинхронным через брокер сообщений». «Очередь должна быть персистентной (сохранение на диск) и реплицированной для отказоустойчивости». «Потребитель должен быть идемпотентным, чтобы при повторах не создавать дубли».
Вывод: Выбор между синхронным и асинхронным взаимодействием – это компромисс между простотой и надёжностью. Для критичных данных, которые нельзя терять, и при допустимой задержке асинхронная очередь – единственно правильное архитектурное решение.
IT-сфера снова переживает бурные времена. AI-технологии влияют на классические подходы, а компании, которые не успевают адаптироваться - теряют позиции. В этой ситуации решает не количество информации, а её качество.