Какие знаешь паттерны для проектирования распределенных систем?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие знаешь паттерны для проектирования распределённых систем
Распределённые системы требуют специальных паттернов для решения уникальных проблем: сетевые задержки, отказы узлов, консистентность данных. Рассмотрим основные паттерны проектирования.
1. Паттерн Circuit Breaker
Предотвращает каскадные отказы при недоступности сервиса.
Состояния:
- Closed — нормальное функционирование
- Open — сервис недоступен, запросы блокируются
- Half-Open — проверка восстановления
Пример:
from circuit_breaker import CircuitBreaker
cb = CircuitBreaker(fail_max=5, reset_timeout=60)
try:
response = cb.call(requests.get, 'http://external-api.com/data')
except CircuitBreakerListener:
# API недоступен, используем fallback
response = get_cached_data()
2. Паттерн Retry (Повторная попытка)
Повторяет операцию при временных ошибках.
Стратегии:
- Exponential backoff — каждый раз ждём дольше (1s, 2s, 4s, 8s)
- Linear backoff — линейное увеличение (1s, 2s, 3s)
- Fixed delay — фиксированная задержка
Пример:
import time
import random
def retry_with_backoff(func, max_retries=3):
for attempt in range(max_retries):
try:
return func()
except Exception as e:
if attempt == max_retries - 1:
raise
wait_time = 2 ** attempt # exponential: 1, 2, 4
wait_time += random.uniform(0, 1) # jitter
time.sleep(wait_time)
3. Паттерн Bulkhead (Переборка)
Изолирует ресурсы для предотвращения распространения отказов.
# Разные thread pools для разных операций
user_service_pool = ThreadPoolExecutor(max_workers=10)
order_service_pool = ThreadPoolExecutor(max_workers=20)
# Если user_service упал, order_service продолжает работать
user_service_pool.submit(get_user, user_id)
order_service_pool.submit(create_order, order_data)
4. Паттерн Timeout
Ограничивает время ожидания ответа от сервиса.
response = requests.get(
'http://slow-api.com/data',
timeout=5 # Макс 5 секунд
)
# Если медленнее — ConnectionTimeout исключение
5. Паттерн Bulkhead для Data
Разделяет данные между узлами (sharding).
Вместо одного Postgres:
PG-1: users 0-999
PG-2: users 1000-1999
PG-3: users 2000-2999
6. Паттерн CQRS (Command Query Responsibility Segregation)
Разделяет чтение (Query) и запись (Command).
Command:
class CreateUserCommand:
def __init__(self, name, email):
self.name = name
self.email = email
command_bus.execute(CreateUserCommand("John", "john@example.com"))
Query:
class GetUserQuery:
def __init__(self, user_id):
self.user_id = user_id
user = query_bus.execute(GetUserQuery(123)) # из read-only replica
Преимущества:
- Различная оптимизация для чтения и записи
- Масштабирование независимо
- Кеширование для queries
7. Паттерн Event Sourcing
Хранит не состояние, а историю событий.
# Вместо: users = {1: {name: "John", status: "active"}}
# Храним события:
events = [
{"type": "UserCreated", "user_id": 1, "name": "John"},
{"type": "UserEmailChanged", "user_id": 1, "email": "john@example.com"},
{"type": "UserActivated", "user_id": 1},
]
# Текущее состояние = воспроизведение всех событий
def get_user_state(user_id):
user = {}
for event in get_events_for_user(user_id):
if event["type"] == "UserCreated":
user = {"id": event["user_id"], "name": event["name"]}
elif event["type"] == "UserEmailChanged":
user["email"] = event["email"]
elif event["type"] == "UserActivated":
user["status"] = "active"
return user
Преимущества:
- Полная история изменений
- Можно восстановить состояние на любой момент времени
- Аудит встроен
- Легче отлаживать
8. Паттерн Saga (Распределённая транзакция)
Управляет долгоживущими транзакциями через микросервисы.
Варианты:
Choreography (хореография)
Order Service: create_order → публикует OrderCreated
↓
Payment Service: слушает OrderCreated → process_payment → публикует PaymentProcessed
↓
Inventory Service: слушает PaymentProcessed → reserve_items → публикует ItemsReserved
↓
Notification Service: слушает ItemsReserved → send_confirmation
Orchestration (оркестровка)
Order Saga Orchestrator:
1. Вызывает Payment Service
2. При успехе → вызывает Inventory Service
3. При успехе → вызывает Notification Service
4. При ошибке → запускает компенсацию (refund)
9. Паттерн Compensating Transaction (Компенсирующая транзакция)
Отменяет успешные операции при отказе.
class CreateOrderSaga:
def execute(self):
# Forward transaction
payment_id = payment_service.charge($100)
inventory_service.reserve_items(items)
if notification_service.send() fails:
# Compensation: отмена
payment_service.refund(payment_id)
inventory_service.unreserve_items(items)
raise Exception("Order creation failed")
10. Паттерн Service Mesh
Отдельный уровень для управления коммуникацией между сервисами.
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ User Svc │ │ Order Svc │ │ Payment Svc │
└──────┬──────┘ └──────┬───────┘ └──────┬───────┘
│sidecar │sidecar │sidecar
↓ ↓ ↓
Envoy ────────────── Envoy ────────────── Envoy
(Service Mesh)
Функции (Istio, Linkerd):
- Load balancing
- Retry & timeout
- Circuit breaking
- Traffic splitting
- Monitoring & observability
11. Паттерн Strangler Fig
Постепенная замена монолита на микросервисы.
1. Новый сервис обёртывает старую функцию
2. Постепенно перенаправляем трафик
3. Полностью заменяем старую функцию
API Gateway
↓
├─ 90% → Old Monolith (User Service)
└─ 10% → New Microservice (User Service v2)
... через месяц
API Gateway
↓
├─ 50% → Old Monolith
└─ 50% → New Microservice
... через 2 месяца
API Gateway
↓
└─ 100% → New Microservice
12. Паттерн API Gateway
Единая точка входа для всех клиентов.
Клиенты → API Gateway → маршрутизация
├→ User Service
├→ Order Service
├→ Payment Service
└→ Notification Service
Функции:
- Аутентификация
- Rate limiting
- Request/response transformation
- Маршрутизация
- Логирование
13. Паттерн Sidecar
Дополнительный контейнер для кроссовых задач.
Под в Kubernetes:
┌─────────────────────────────────┐
│ Application Container (User Svc)│
├─────────────────────────────────┤
│ Sidecar Container (Logging) │
├─────────────────────────────────┤
│ Sidecar Container (Monitoring) │
└─────────────────────────────────┘
Паттерны мониторинга и отладки
Distributed Tracing
Пользовательский запрос (request_id = "abc-123")
↓
API Gateway (trace: abc-123, span: api-1)
↓
User Service (trace: abc-123, span: user-1)
↓
Database (trace: abc-123, span: db-1)
Каждый сервис логирует с одним request_id
Инструменты: Jaeger, Zipkin, DataDog
Health Checks & Liveness Probes
@app.get("/health")
def health():
if db.is_connected() and cache.is_connected():
return {"status": "healthy"}
else:
return {"status": "unhealthy"}, 503
Значение для System Analyst
System Analyst должен:
- Выбирать подходящие паттерны для архитектуры
- Понимать trade-offs каждого паттерна
- Проектировать отказоустойчивые системы
- Планировать мониторинг и наблюдаемость
- Документировать архитектуру паттернов
- Обучать команду лучшим практикам