Files
sa-lessons/modules/module2/sections/04-data-management.md
T
Alexander Abakumov 15e744da49 Initial commit: Complete Software Architecture course with 11 modules
- 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
2025-09-09 22:08:07 +03:00

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