- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
202 lines
6.0 KiB
Markdown
202 lines
6.0 KiB
Markdown
# Управление данными в микросервисах
|
||
|
||
## Навигация
|
||
- [🏠 Главная страница курса](../../../README.md)
|
||
- [📚 Модуль 2](../README.md)
|
||
|
||
---
|
||
|
||
## База данных на сервис
|
||
|
||
**Принцип:** Каждый микросервис имеет собственную базу данных.
|
||
|
||
### Преимущества:
|
||
- Независимость данных
|
||
- Разные типы БД для разных задач
|
||
- Независимое масштабирование
|
||
|
||
### Недостатки:
|
||
- Сложность транзакций
|
||
- Проблемы с консистентностью
|
||
- Дублирование данных
|
||
|
||
## Паттерны управления данными
|
||
|
||
### 1. Saga Pattern
|
||
**Определение:** Паттерн для управления распределенными транзакциями.
|
||
|
||
#### Choreography Saga
|
||
```java
|
||
// Order Service
|
||
public class OrderService {
|
||
public void createOrder(CreateOrderRequest request) {
|
||
Order order = new Order(request);
|
||
orderRepository.save(order);
|
||
|
||
// публикуем событие
|
||
eventPublisher.publish(new OrderCreatedEvent(order.getId(), request.getItems()));
|
||
}
|
||
}
|
||
|
||
// Inventory Service
|
||
@EventHandler
|
||
public class InventoryEventHandler {
|
||
public void handleOrderCreated(OrderCreatedEvent event) {
|
||
try {
|
||
inventoryService.reserveItems(event.getItems());
|
||
eventPublisher.publish(new ItemsReservedEvent(event.getOrderId()));
|
||
} catch (InsufficientStockException e) {
|
||
eventPublisher.publish(new OrderCancelledEvent(event.getOrderId()));
|
||
}
|
||
}
|
||
}
|
||
|
||
// Payment Service
|
||
@EventHandler
|
||
public class PaymentEventHandler {
|
||
public void handleItemsReserved(ItemsReservedEvent event) {
|
||
try {
|
||
paymentService.processPayment(event.getOrderId());
|
||
eventPublisher.publish(new PaymentProcessedEvent(event.getOrderId()));
|
||
} catch (PaymentFailedException e) {
|
||
eventPublisher.publish(new OrderCancelledEvent(event.getOrderId()));
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Orchestration Saga
|
||
```java
|
||
@Service
|
||
public class OrderOrchestrator {
|
||
public void processOrder(CreateOrderRequest request) {
|
||
Order order = orderService.createOrder(request);
|
||
|
||
try {
|
||
// шаг 1: резервирование товаров
|
||
inventoryService.reserveItems(order.getId(), request.getItems());
|
||
|
||
// шаг 2: обработка платежа
|
||
paymentService.processPayment(order.getId(), request.getPayment());
|
||
|
||
// шаг 3: подтверждение заказа
|
||
orderService.confirmOrder(order.getId());
|
||
|
||
} catch (Exception e) {
|
||
// компенсирующие транзакции
|
||
compensateOrder(order.getId());
|
||
}
|
||
}
|
||
|
||
private void compensateOrder(OrderId orderId) {
|
||
try {
|
||
inventoryService.releaseItems(orderId);
|
||
paymentService.refundPayment(orderId);
|
||
orderService.cancelOrder(orderId);
|
||
} catch (Exception e) {
|
||
// логирование ошибок компенсации
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. CQRS (Command Query Responsibility Segregation)
|
||
**Определение:** Разделение команд и запросов.
|
||
|
||
```java
|
||
// Command Side
|
||
@Service
|
||
public class OrderCommandService {
|
||
public void createOrder(CreateOrderCommand command) {
|
||
Order order = new Order(command);
|
||
orderRepository.save(order);
|
||
|
||
// обновляем read model
|
||
orderReadModelService.updateReadModel(order);
|
||
}
|
||
}
|
||
|
||
// Query Side
|
||
@Service
|
||
public class OrderQueryService {
|
||
public OrderView getOrderView(OrderId orderId) {
|
||
return orderReadModelRepository.findById(orderId);
|
||
}
|
||
|
||
public List<OrderView> getOrdersByCustomer(CustomerId customerId) {
|
||
return orderReadModelRepository.findByCustomerId(customerId);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. Event Sourcing
|
||
**Определение:** Хранение событий вместо состояния.
|
||
|
||
```java
|
||
@Entity
|
||
public class OrderEvent {
|
||
private Long id;
|
||
private String aggregateId;
|
||
private String eventType;
|
||
private String eventData;
|
||
private LocalDateTime occurredAt;
|
||
}
|
||
|
||
@Service
|
||
public class OrderEventStore {
|
||
public void saveEvent(OrderEvent event) {
|
||
eventRepository.save(event);
|
||
}
|
||
|
||
public List<OrderEvent> getEvents(String aggregateId) {
|
||
return eventRepository.findByAggregateIdOrderByOccurredAt(aggregateId);
|
||
}
|
||
}
|
||
|
||
@Service
|
||
public class OrderProjectionService {
|
||
public OrderView buildOrderView(String orderId) {
|
||
List<OrderEvent> events = eventStore.getEvents(orderId);
|
||
OrderView view = new OrderView();
|
||
|
||
for (OrderEvent event : events) {
|
||
applyEvent(view, event);
|
||
}
|
||
|
||
return view;
|
||
}
|
||
}
|
||
```
|
||
|
||
## Консистентность данных
|
||
|
||
### Типы консистентности:
|
||
|
||
#### 1. Strong Consistency
|
||
- Все узлы видят одинаковые данные
|
||
- Сложно в распределенных системах
|
||
- Высокая задержка
|
||
|
||
#### 2. Eventual Consistency
|
||
- Данные в итоге станут консистентными
|
||
- Подходит для большинства случаев
|
||
- Низкая задержка
|
||
|
||
#### 3. Weak Consistency
|
||
- Нет гарантий консистентности
|
||
- Используется редко
|
||
|
||
### Паттерны для консистентности:
|
||
|
||
#### 1. Two-Phase Commit (2PC)
|
||
**Проблема:** Блокирующий протокол
|
||
**Решение:** Использовать Saga вместо 2PC
|
||
|
||
#### 2. Three-Phase Commit (3PC)
|
||
**Улучшение:** Меньше блокировок
|
||
**Проблема:** Все еще сложный
|
||
|
||
#### 3. Consensus Algorithms
|
||
- **Raft** — выбор лидера
|
||
- **Paxos** — консенсус в распределенных системах
|