Какие существуют подходы к обработке исключительных ситуаций в больших распределённых системах, и как выбирать между retry, circuit breaker и отложенным откатом транзакций?
Кратко — основные подходы и практические критерии выбора между retry, circuit breaker и отложенным откатом (саги/компенсации). Подходы (суть и когда использовать) - Retry (повтор попыток) - Что: повтор запроса к сервису при временных ошибках. - Требования: операция идемпотентна или есть дедупликация; ошибки транзиентны (сети, таймауты, временная перегрузка). - Как: экспоненциальный backoff + jitter, максимальное число попыток, таймаут на каждую попытку. - Формула (пример): задержка ti=min(tmax,t0⋅2i)+jittert_i = \min(t_{\max}, t_0 \cdot 2^{i}) + \text{jitter}ti=min(tmax,t0⋅2i)+jitter. - Circuit breaker (автоматическое «размыкание» вызовов) - Что: мониторит ошибочные ответы и при высоком уровне ошибок разрывает вызовы к убывающему сервису, быстро возвращая ошибку или fallback. - Когда: ошибки устойчивые/постоянные или сервис перегружен; важно избегать усугубления проблем downstream. - Состояния: CLOSED → OPEN (при FFF ошибках за окно) → HALF‑OPEN (проверка) → CLOSED. - Параметры: порог ошибок FFF, окно наблюдения WWW, время открытого состояния TopenT_{open}Topen, число проб в HALF‑OPEN HHH. - Отложенный откат / саги (compensating transactions) - Что: разбивка распределённой транзакции на последовательность локальных транзакций + компенсаторы; откат выполняется отдельно при ошибке. - Когда: долгие бизнес‑процессы, несколько сервисов, ACID недостижим или слишком дорог; согласие на eventual consistency. - Требования: реализуемые компенсаторы, прозрачность состояния процесса, надёжный оркестратор/хореография, идемпотентность компенсаторов. Дополнительные паттерны (часто вместе с вышеупомянутыми) - Timeouts и контролируемая длительность операций. - Bulkhead (разделение ресурсов по компонентам), rate limiting, backpressure. - Очереди/асинхронность для буферизации запросов при перегрузке. - Фоллбеки и деградация функционала. Как выбирать — практические критерии - Тип ошибки: - Транзиентная сеть/таймаут → retry (+ backoff). - Постоянная ошибка (логическая, аутентификация, конфиг) или устойчивый перегруз → circuit breaker + быстрый фейл. - Ошибка в многошаговой распределённой операции → saga/компенсация. - Стоимость повтора: - Низкая и идемпотентная → retry. - Высокая (дорогая операция, сторонний платёж, внешние side‑effects) → избегать автоматических retry; предпочесть circuit breaker или ручной откат. - Требования к согласованности: - Нужна строгая ACID → централизованные транзакции (2PC) — только при явной необходимости (ограничено масштабом). - Допустима eventual consistency → саги/компенсации. - Чувствительность к задержкам: - Низкая задержка в синхронном пути → prefer circuit breaker/fallback вместо долгих retry. - Асинхронный фон → можно использовать очередь + повтор/компенсацию. - Идемпотентность: - Если нет — нельзя бесконтрольно ретраить; нужен дедупликатор или компенсация. Практические значения/шаблоны (рекомендации) - Retry: NNN попыток, где N∈{3,5}N \in \{3,5\}N∈{3,5}; стартовая задержка t0t_0t0 — 505050-200200200 ms; cap tmaxt_{\max}tmax — 111-555 s; добавлять jitter. - Пример: ti=min(5 s,100 ms⋅2i)+U(0,100 ms)t_i = \min(5\text{ s}, 100\text{ ms}\cdot 2^{i}) + U(0,100\text{ ms})ti=min(5 s,100 ms⋅2i)+U(0,100 ms), i=0..N−1i=0..N-1i=0..N−1. - Circuit breaker: открыть при FFF ошибках за окно WWW (например F=5,W=10 sF=5, W=10\text{ s}F=5,W=10 s), держать открытым TopenT_{open}Topen (например 303030-606060 s), в HALF‑OPEN пробовать HHH запросов (например H=1H=1H=1-555). - Sagas: проектировать явные компенсаторы для каждой шага; хранить статус процесса; эвристики таймаута ожидания отката/компенсации. Комбинации и последовательность действий - Часто используют вместе: retry (с ограничением) + circuit breaker (чтобы не доводить до коллапса) + при распределённых процессах — саги. - Пример стратегии: при кратковременных сетевых ошибках — retry N=3N=3N=3; если частые ошибки — circuit breaker открывает путь к fallback; для multi‑service бизнес‑транзакций — saga с компенсаторами и мониторингом. Мониторинг и метрики (обязательны) - Счетчики: error rate, latencies, retries per request, circuit open count, saga failures. - Алерты по росту error rate и частым открытиям circuit breaker. Краткое правило решения - Транзиентная ошибка + идемпотентность → retry. - Устойчивая/перегруз → circuit breaker (с fallback). - Нужна согласованная многошаговая операция между сервисами → saga/компенсация. Если нужно — могу предложить конкретные конфигурации параметров для вашего кейса (тип нагрузки, SLAs, требования к консистентности).
Подходы (суть и когда использовать)
- Retry (повтор попыток)
- Что: повтор запроса к сервису при временных ошибках.
- Требования: операция идемпотентна или есть дедупликация; ошибки транзиентны (сети, таймауты, временная перегрузка).
- Как: экспоненциальный backoff + jitter, максимальное число попыток, таймаут на каждую попытку.
- Формула (пример): задержка ti=min(tmax,t0⋅2i)+jittert_i = \min(t_{\max}, t_0 \cdot 2^{i}) + \text{jitter}ti =min(tmax ,t0 ⋅2i)+jitter.
- Circuit breaker (автоматическое «размыкание» вызовов)
- Что: мониторит ошибочные ответы и при высоком уровне ошибок разрывает вызовы к убывающему сервису, быстро возвращая ошибку или fallback.
- Когда: ошибки устойчивые/постоянные или сервис перегружен; важно избегать усугубления проблем downstream.
- Состояния: CLOSED → OPEN (при FFF ошибках за окно) → HALF‑OPEN (проверка) → CLOSED.
- Параметры: порог ошибок FFF, окно наблюдения WWW, время открытого состояния TopenT_{open}Topen , число проб в HALF‑OPEN HHH.
- Отложенный откат / саги (compensating transactions)
- Что: разбивка распределённой транзакции на последовательность локальных транзакций + компенсаторы; откат выполняется отдельно при ошибке.
- Когда: долгие бизнес‑процессы, несколько сервисов, ACID недостижим или слишком дорог; согласие на eventual consistency.
- Требования: реализуемые компенсаторы, прозрачность состояния процесса, надёжный оркестратор/хореография, идемпотентность компенсаторов.
Дополнительные паттерны (часто вместе с вышеупомянутыми)
- Timeouts и контролируемая длительность операций.
- Bulkhead (разделение ресурсов по компонентам), rate limiting, backpressure.
- Очереди/асинхронность для буферизации запросов при перегрузке.
- Фоллбеки и деградация функционала.
Как выбирать — практические критерии
- Тип ошибки:
- Транзиентная сеть/таймаут → retry (+ backoff).
- Постоянная ошибка (логическая, аутентификация, конфиг) или устойчивый перегруз → circuit breaker + быстрый фейл.
- Ошибка в многошаговой распределённой операции → saga/компенсация.
- Стоимость повтора:
- Низкая и идемпотентная → retry.
- Высокая (дорогая операция, сторонний платёж, внешние side‑effects) → избегать автоматических retry; предпочесть circuit breaker или ручной откат.
- Требования к согласованности:
- Нужна строгая ACID → централизованные транзакции (2PC) — только при явной необходимости (ограничено масштабом).
- Допустима eventual consistency → саги/компенсации.
- Чувствительность к задержкам:
- Низкая задержка в синхронном пути → prefer circuit breaker/fallback вместо долгих retry.
- Асинхронный фон → можно использовать очередь + повтор/компенсацию.
- Идемпотентность:
- Если нет — нельзя бесконтрольно ретраить; нужен дедупликатор или компенсация.
Практические значения/шаблоны (рекомендации)
- Retry: NNN попыток, где N∈{3,5}N \in \{3,5\}N∈{3,5}; стартовая задержка t0t_0t0 — 505050-200200200 ms; cap tmaxt_{\max}tmax — 111-555 s; добавлять jitter.
- Пример: ti=min(5 s,100 ms⋅2i)+U(0,100 ms)t_i = \min(5\text{ s}, 100\text{ ms}\cdot 2^{i}) + U(0,100\text{ ms})ti =min(5 s,100 ms⋅2i)+U(0,100 ms), i=0..N−1i=0..N-1i=0..N−1.
- Circuit breaker: открыть при FFF ошибках за окно WWW (например F=5,W=10 sF=5, W=10\text{ s}F=5,W=10 s), держать открытым TopenT_{open}Topen (например 303030-606060 s), в HALF‑OPEN пробовать HHH запросов (например H=1H=1H=1-555).
- Sagas: проектировать явные компенсаторы для каждой шага; хранить статус процесса; эвристики таймаута ожидания отката/компенсации.
Комбинации и последовательность действий
- Часто используют вместе: retry (с ограничением) + circuit breaker (чтобы не доводить до коллапса) + при распределённых процессах — саги.
- Пример стратегии: при кратковременных сетевых ошибках — retry N=3N=3N=3; если частые ошибки — circuit breaker открывает путь к fallback; для multi‑service бизнес‑транзакций — saga с компенсаторами и мониторингом.
Мониторинг и метрики (обязательны)
- Счетчики: error rate, latencies, retries per request, circuit open count, saga failures.
- Алерты по росту error rate и частым открытиям circuit breaker.
Краткое правило решения
- Транзиентная ошибка + идемпотентность → retry.
- Устойчивая/перегруз → circuit breaker (с fallback).
- Нужна согласованная многошаговая операция между сервисами → saga/компенсация.
Если нужно — могу предложить конкретные конфигурации параметров для вашего кейса (тип нагрузки, SLAs, требования к консистентности).