- 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** — консенсус в распределенных системах
|