BA & SA | 10000 Interview questions
10.2K subscribers
174 photos
14 videos
344 links
Вопросы и задачи, которые задают на собеседованиях на позицию Бизнес и Системного аналитика. По вопросам сотрудничества- @DeliveryManager7
Download Telegram
👩‍🏫Объяснение:
Идемпотентность — это фундаментальное свойство операций в распределенных системах, которое гарантирует, что многократное выполнение одной и той же операции (с одинаковыми параметрами) приведет к тому же результату, что и однократное выполнение.

🔍 Почему это критически важно в интеграциях?
В реальных условиях сетевые сбои, таймауты и проблемы с подключением — обычное дело. Клиентское приложение, не получив ответ, может отправить запрос повторно. Без идемпотентности это приведет к катастрофическим последствиям:

Двойное списание денег при повторном платежном запросе
Создание дубликатов заказов
Многократное начисление бонусов

💡 Практические примеры:

Платежная операция:

Клиент нажимает "Оплатить", но не видит ответ из-за обрыва сети
Приложение отправляет запрос снова
С идемпотентностью: Система распознает, что это тот же платеж (по уникальному idempotency-key), и возвращает результат первого списания
Без идемпотентности: Деньги спишутся дважды

Изменение статуса заказа:

PUT /orders/{id}/status с телом {"status": "shipped"}
Сколько бы раз ни вызывался этот запрос, заказ останется в статусе "shipped"

⚙️ Как это реализуется технически:

Использование уникального ключа идемпотентности:

```http
POST /api/payments
Idempotency-Key: a1b2c3d4-5678-90ef-ghij-klmnopqrstuv
Сервер запоминает результат обработки для каждого ключа и возвращает его при повторных запросах
```

HTTP-методы:

GET, PUT, DELETE по спецификации должны быть идемпотентными

POST — не идемпотентен (создает новый ресурс), поэтому для POST-операций нужна дополнительная реализация

Бизнес-логика:

Проверка "была ли уже выполнена эта операция?"
Использование уникальных идентификаторов транзакций
№4626 категория вопросов: #INTEGRATION
4626. Какой паттерн интеграции предполагает, что система A публикует событие, а система B и система C независимо реагируют на него, не зная друг о друге?
Anonymous Quiz
12%
API Gateway
18%
Паттерн "Цепочка ответственности"
66%
Шина событий (Event Bus)
4%
Прямая интеграция Point-to-Point
👩‍🏫Объяснение:
Шина событий (Event Bus) — это архитектурный паттерн, который реализует модель публикации-подписки (Pub/Sub) для слабосвязанной асинхронной интеграции между системами.

🔍 Как это работает на практике:

Издатель (Publisher): Система A выполняет какое-то действие и публикует событие в шину
Шина событий: Центральный компонент, который принимает события и рассылает их подписчикам
Подписчики (Subscribers): Системы B и C заранее подписались на определенные типы событий и получают их автоматически
💡 Реальный пример из e-commerce:

text
Событие: "Заказ №1234 создан"
Издатель: Сервис заказов
Подписчики:
- Сервис уведомлений → отправляет email клиенту
- Сервис аналитики → обновляет статистику продаж
- Сервис склада → резервирует товар
- Сервис рекомендаций → обновляет модели машинного обучения
Все эти сервисы работают независимо друг от друга и даже не знают о существовании других подписчиков.

🎯 Ключевые преимущества шины событий:

Слабая связанность:
Издатель не знает, кто и как обработает его событие
Можно добавлять новых подписчиков без изменения кода издателя
Пример: добавили новый сервис "Мониторинг качества" — просто подписались на события
Масштабируемость:
Каждый подписчик работает в своем темпе
Можно запускать несколько экземпляров одного подписчика для обработки нагрузки
Отказоустойчивость:
Если один подписчик упал, другие продолжают работать
События могут сохраняться в шине до обработки
Гибкость:
Разные системы могут реагировать на одно событие по-своему
Легко переключать обработчиков или добавлять новые

⚙️ Технические реализации:

Apache Kafka: Для высоконагруженных систем, с сохранением истории событий
RabbitMQ: Классический message broker с поддержкой Pub/Sub
AWS SNS/SQS, Azure Service Bus: Облачные решения
Redis Pub/Sub: Для простых сценариев с небольшой нагрузкой
№4627 категория вопросов: #INTEGRATION
4627. Какой механизм предотвращает "лавину" запросов к упавшему сервису, временно разрывая соединение и возвращая заготовленный ответ?
Anonymous Quiz
52%
Circuit Breaker
8%
Retry Pattern
20%
Rate Limiting
20%
Load Balancing
👩‍🏫Объяснение:
Circuit Breaker (автоматический выключатель) — это паттерн устойчивости, который предотвращает каскадные сбои в распределенных системах, временно блокируя вызовы к неработающему сервису.

🔍 Аналогия из реальной жизни:
Представьте электрический автомат в квартире:

При коротком замыкании автомат разрывает цепь
Это предотвращает возгорание и повреждение приборов
Через некоторое время можно попробовать включить снова
Circuit Breaker работает по тому же принципу!
💡 Как это работает в интеграциях:

Закрытое состояние (Closed):
Запросы свободно проходят к удаленному сервису
Мониторится количество ошибок
text
Сервис A -----> Сервис B [работает нормально]
Открытое состояние (Open):
При превышении порога ошибок (например, 50% за последние 10 секунд)
Circuit Breaker разрывает цепь
Все последующие запросы немедленно отклоняются без попыток вызова
Возвращается заготовленный ответ (fallback) или ошибка
text
Сервис A --X--> Сервис B [упал]
↳ Возврат: "Сервис временно недоступен"
Полуоткрытое состояние (Half-Open):
Через заданный таймаут пропускается пробный запрос
Если успешно → возврат в закрытое состояние
Если ошибка → снова открытое состояние
🎯 Почему это критически важно:

Без Circuit Breaker:

Сервис B начинает медленно работать
Сервис A продолжает слать запросы и ждать таймаута
Потоки в сервисе A блокируются в ожидании
Сервис A тоже начинает тормозить
Клиенты сервиса A начинают перезапрашивать...
Лавина запросов добивает оба сервиса
С Circuit Breaker:

Сервис B начинает сбоить
Circuit Breaker обнаруживает это и разрывает цепь
Сервис A сразу получает fallback-ответ
Ресурсы сервиса A не блокируются
Сервис B получает передышку для восстановления
Когда сервис B восстановится, Circuit Breaker снова откроет доступ
⚙️ Технические реализации:

Hystrix (от Netflix) — классическая реализация
Resilience4j — современная альтернатива для Java
Polly — для .NET
Встроенные механизмы в Spring Cloud, Istio
👨‍💼 Конфигурация, которую определяет аналитик:

yaml
circuit-breaker:
failure-threshold: 50% # Порог ошибок для разрыва цепи
timeout: 5s # Таймаут для каждого вызова
reset-timeout: 30s # Время в открытом состоянии
half-open-calls: 3 # Количество пробных запросов
1
№4628 категория вопросов: #INTEGRATION
4628. Какой паттерн преобразует интерфейс одного класса в интерфейс, ожидаемый клиентом, позволяя работать вместе классам с несовместимыми интерфейсами?
Anonymous Quiz
71%
Адаптер
13%
Фасад
10%
Прокси
6%
Декоратор
👩‍🏫Объяснение:
Паттерн Адаптер (Adapter) — это структурный паттерн проектирования, который действует как «переходник» или «конвертер» между двумя несовместимыми интерфейсами. Он позволяет объектам с разными интерфейсами работать вместе без изменения их исходного кода.

🔍 Ключевая аналогия:
Представьте путешественника из Европы в США:

Европейская вилка (круглые штыри) ↔️ Американская розетка (плоские отверстия)

Адаптер преобразует один тип разъема в другой

Вилка и розетка не меняются, но могут работать вместе

💡 Пример из интеграций:

Ситуация: У вас есть новая система, которая ожидает данные в формате JSON через REST API, а старая система отправляет данные в фиксированном текстовом формате по FTP.

Без адаптера: Пришлось бы переписывать одну из систем.

С адаптером:

Адаптер слушает FTP-сервер старой системы
Читает текстовый файл фиксированного формата
Парсит и преобразует данные в JSON-структуру
Вызывает REST API новой системы с подготовленными данными

Техническая реализация:

```java
// Старый интерфейс (текстовый формат по FTP)
interface OldSystemService {
String fetchDataFromFTP();
}

// Новый интерфейс (JSON по REST)
interface NewSystemService {
void sendJsonData(String json);
}

// Адаптер, который преобразует старый формат в новый
class SystemAdapter implements NewSystemService {
private OldSystemService oldSystem;

@Override
public void sendJsonData(String json) {
// 1. Получаем данные из старой системы
String textData = oldSystem.fetchDataFromFTP();

// 2. Преобразуем текстовый формат в JSON
String convertedJson = convertTextToJson(textData);

// 3. Отправляем в новую систему
// ... вызов REST API
}
}
```

🎯 Преимущества паттерна Адаптер:

Сохранение legacy-кода: Не нужно изменять старые, проверенные системы

Постепенная миграция: Можно поэтапно переходить на новые технологии

Слабая связанность: Системы не зависят друг от друга напрямую

Переиспользование: Один адаптер можно использовать для интеграции с несколькими системами
№4629 категория вопросов: #INTEGRATION
4629. Какой подход к интеграции предполагает, что каждая система работает со своей собственной базой данных, а обмен данными происходит только через API?
Anonymous Quiz
7%
Общая база данных (Shared Database)
82%
Разделенные базы данных (Database per Service)
0%
Единая база данных (Single Database)
12%
Репликация базы данных (Database Replication)
👩‍🏫Объяснение:
Паттерн "Database per Service" (База данных на сервис) — это фундаментальный принцип микросервисной архитектуры, при котором каждый сервис управляет своей собственной базой данных, и другие сервисы могут получать доступ к этим данным только через публичный API сервиса-владельца.

🔍 Почему это важно в современных архитектурах:

Старый подход (антипаттерн): Общая база данных
Все сервисы пишут и читают из одной БД
Изменение схемы БД ломает несколько сервисов сразу
Невозможно выбрать оптимальную СУБД для каждой задачи
Нарушается принцип инкапсуляции
Новый подход: Database per Service

text
Сервис Заказов Сервис Платежей Сервис Каталога
↓ ↓ ↓
[БД Заказов] [БД Платежей] [БД Товаров]
MySQL PostgreSQL MongoDB
💡 Ключевые принципы:

Владение данными: Каждый сервис — единственный владелец своих данных

Инкапсуляция: Детали хранения данных скрыты внутри сервиса

API как контракт: Доступ к данным только через четко определенный API

Независимое развертывание: Можно обновлять схему БД одного сервиса, не затрагивая другие

🎯 Преимущества подхода:

Независимость технологий:

Сервис Заказов может использовать реляционную БД (MySQL)
Сервис Аналитики — колоночную (ClickHouse)
Сервис Рекомендаций — графовую (Neo4j)

Масштабируемость:

Каждую БД можно масштабировать независимо
Можно шардировать БД по бизнес-доменам
Отказоустойчивость:
Падение одной БД не влияет на другие сервисы
Можно настроить репликацию для каждой БД отдельно

Гибкость развития:

Можно менять схему БД внутри сервиса без согласования с другими командами
Легче рефакторить и оптимизировать

⚡️ Вызовы и решения:

Проблема: Как обеспечить согласованность данных между сервисами?
Решение: Паттерн Сага (Saga) для распределенных транзакций

Проблема: Как выполнять сложные запросы, требующие данных из нескольких сервисов?
Решение:

API Composition: Агрегация данных на уровне API Gateway

Командное разделение ответственности (CQRS): Отдельные модели для чтения и записи

Денормализованные копии данных: Репликация нужных данных в другой сервис через события

👨‍💼 Практический пример от аналитика:

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

Реализация:

Сервис Каталога (владеет основной информацией о товаре)
Сервис Склада (владеет информацией о наличии)
Сервис Отзывов (владеет отзывами и рейтингами)
API Gateway делает параллельные вызовы ко всем трем сервисам и агрегирует результат
1
№4630 категория вопросов: #INTEGRATION
4630. Какой механизм позволяет временно хранить результаты запросов и быстро возвращать их при повторных обращениях, уменьшая нагрузку на источник данных?
Anonymous Quiz
92%
Кэширование
2%
Шардирование
5%
Репликация
1%
Индексирование
👩‍🏫Объяснение:
Кэширование — это механизм хранения копии данных в быстродоступном хранилище, чтобы ускорить получение этих данных при повторных запросах и снизить нагрузку на первичный источник.

🔍 Простая аналогия:
Представьте библиотеку:

Первичный источник: Книгохранилище в подвале (медленно)
Кэш: Полка на абонементе (быстро)

Библиотекарь: Сначала проверяет полку, если книги нет — идет в хранилище

💡 Как кэширование работает в интеграциях:

Без кэша:

```text
Клиент → Запрос → Сервис → [Сложный расчет/Запрос к БД] → Ответ
↑ (каждый раз заново!) ↓
└─────────────────────────────────────────────────────┘
С кэшем:

text
Клиент → Запрос → Сервис → [Проверка кэша]

[Данные в кэше?] → Да → Возврат из кэша (быстро!)
↓ Нет
[Выполнение запроса к источнику]

[Сохранение в кэш] → Возврат клиенту
```

🎯 Типы кэширования в интеграциях:

Кэш на стороне клиента:
Браузер кэширует статические ресурсы (CSS, JS, изображения)
Mobile app кэширует данные локально
Срок жизни: от часов до дней

Кэш на стороне сервера:

```nginx
# Пример настройки кэширования в Nginx
location /api/products {
proxy_cache products_cache;
proxy_cache_valid 200 5m; # Кэшировать успешные ответы 5 минут
proxy_pass http://product-service;
}
Распределенный кэш:

Redis, Memcached, Hazelcast

Общий кэш для всех экземпляров сервиса
```

Пример использования:

```java
// Spring Cache с Redis
@Cacheable(value = "products", key = "#id")
public Product getProduct(String id) {
return productRepository.findById(id); // Дорогой запрос к БД
}
```

⚡️ Стратегии кэширования:

Cache-Aside (Lazy Loading):

Проверить кэш → если нет → получить из источника → сохранить в кэш

Самый распространенный подход

Write-Through:

Запись сначала в кэш, затем в источник
Гарантирует актуальность данных

Write-Behind:

Запись сначала в кэш, затем асинхронно в источник
Высокая производительность записи

🔥 Практические примеры:

Пример 1: Кэширование справочников

Города, валюты, типы документов
Меняются редко, запрашиваются часто
Можно кэшировать на 24 часа

Пример 2: Кэширование результатов сложных расчетов

Аналитические отчеты
Рекомендательные алгоритмы
Кэшировать на 1 час или до изменения исходных данных

Пример 3: Кэширование сессий пользователей

Информация о пользователе после логина
Сохранять в Redis с TTL 30 минут

⚠️ Проблемы и решения:

Проблема: Устаревшие данные (Stale Data)
Решение:

Инвалидация кэша при изменении данных

TTL (Time-To-Live) — автоматическое удаление старых записей

Версионирование ключей кэша

Проблема: "Пробоина кэша" (Cache Miss Storm)
Решение:

Предзагрузка популярных данных
Использование "теплого" кэша
Блокировка (Locking) при первом запросе

👨‍💼 Что должен учитывать системный аналитик:

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

Проектировать стратегию инвалидации:

Как узнавать об изменениях данных?
Нужна ли синхронная инвалидация или можно по TTL?
Определять требования к актуальности:
"Данные должны быть актуальны в течение 5 минут"
"Допустима задержка до 1 часа для аналитических данных"
Учитывать объемы данных:
Сколько памяти потребуется?
Нужен ли distributed кэш?
№4631 категория вопросов: #INTEGRATION
4631. Какой протокол обмена сообщениями использует модель "публикация-подписка" (pub/sub) и гарантирует доставку сообщений даже при временной недоступности получателя?
Anonymous Quiz
4%
HTTP
26%
WebSocket
59%
AMQP
11%
SMTP
👩‍🏫Объяснение:
AMQP (Advanced Message Queuing Protocol) — это открытый стандартный протокол прикладного уровня для асинхронной передачи сообщений между системами. Он поддерживает модель публикации-подписки (pub/sub) и гарантирует доставку сообщений даже при временных сбоях.

🔍 Ключевые особенности AMQP:

Гарантии доставки:

At-most-once (максимум один раз)
At-least-once (минимум один раз)
Exactly-once (ровно один раз) — через механизмы идемпотентности

Модели обмена:

Очереди (Queues): Точечная доставка
Топики/Exchange (Topics): Публикация-подписка
RPC: Запрос-ответ

Надежность:

Подтверждение получения (acknowledgments)
Сохранение сообщений на диск
Транзакционность

💡 Как работает AMQP в интеграциях:

Архитектурные компоненты:
Producer/Publisher: Отправитель сообщений
Exchange: Маршрутизатор сообщений
Queue: Очередь сообщений
Consumer/Subscriber: Получатель сообщений

Пример потока:

```text
Producer → [Exchange] → [Binding Rules] → [Queue] → Consumer
↓ ↓
(по routing key) (сохраняется до обработки)
```

🎯 Реализации AMQP:

RabbitMQ — самая популярная реализация

```python
# Пример публикации сообщения в RabbitMQ
channel.basic_publish(
exchange='orders',
routing_key='new.order',
body=json.dumps(order_data),
properties=pika.BasicProperties(
delivery_mode=2, # Сохранять на диск
)
)
Apache Qpid
```

Azure Service Bus (частичная поддержка AMQP)

🔥 Практические сценарии использования:

Сценарий 1: Обработка заказов в e-commerce

Пользователь создает заказ → сообщение в очередь new_orders

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

Сценарий 2: Сбор логов и метрик

Все сервисы публикуют логи в exchange logs
Exchange маршрутизирует логи в разные очереди по severity
Сервис мониторинга и сервис аналитики подписываются на нужные очереди

Сценарий 3: Фоновая обработка задач

Пользователь загружает видео → сообщение в очередь video_processing
Воркеры берут задачи из очереди и обрабатывают
Можно масштабировать количество воркеров по нагрузке

⚡️ Преимущества AMQP:

Надежность:

Сообщения сохраняются на диск
Подтверждение получения
Автоматическое восстановление соединений

Гибкость маршрутизации:

Direct (точная маршрутизация по ключу)
Fanout (всем подписчикам)
Topic (по шаблону ключа)
Headers (по заголовкам сообщения)

Управление потоком:

QoS (Quality of Service) — ограничение неподтвержденных сообщений
Поддержка backpressure

Кластеры и отказоустойчивость:

Репликация очередей между узлами
Автоматическое переподключение при сбоях

⚠️ Сложности и решения:

Проблема: Гарантированный порядок доставки
Решение: Использовать одну очередь на потребителя или механизмы sequencing

Проблема: Накопление сообщений при сбое потребителя
Решение: Dead Letter Queues (DLQ) + алертинг

Проблема: Персистентность vs производительность
Решение: Балансировать между delivery_mode=1 (transient) и delivery_mode=2 (persistent)

👨‍💼 Роль системного аналитика:

Проектирование топологии обмена сообщениями:
Какие exchange, очереди и routing keys нужны?
Какие bindings между ними?
Определение требований к доставке:
Нужны ли гарантии exactly-once?
Какие таймауты и retry политики?
Как обрабатывать poison messages?
Проектирование форматов сообщений:

```json
{
"message_id": "uuid",
"timestamp": "2024-01-15T10:30:00Z",
"type": "order.created",
"version": "1.0",
"payload": {...},
"metadata": {...}
}
```

Планирование мониторинга:

Длина очередей
Latency обработки сообщений
Rate публикации/потребления
🔥2
№4632 категория вопросов: #INTEGRATION
4632. Какой механизм позволяет системе А отправлять запросы системе Б через промежуточный сервер, который скрывает сетевую структуру внутренней системы?
Anonymous Quiz
65%
Прокси-сервер
13%
Фаервол
11%
DNS-сервер
11%
Балансировщик нагрузки