← Назад к вопросам
Что такое распределенная система?
3.0 Senior🔥 191 комментариев
#REST API и микросервисы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое распределённая система?
Распределённая система — это набор независимых компьютеров (узлов) или процессов, которые работают параллельно и взаимодействуют между собой через сеть для достижения общей цели. При этом каждый узел имеет собственную память, процессор и может выполнять операции независимо от других.
Определение и характеристики
Ключевые признаки распределённой системы:
- Множество автономных компонентов — каждый узел может функционировать независимо
- Отсутствие глобальных часов — синхронизация времени между узлами сложна
- Сетевое взаимодействие — узлы общаются через сетевые протоколы
- Отказоустойчивость — выход из строя одного узла не должен повалить всю систему
- Масштабируемость — система должна работать при добавлении новых узлов
Архитектура распределённой системы
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Node 1 │<------>│ Node 2 │<------>│ Node 3 │
│ Process 1 │ Network │ Process 2 │ Network │ Process 3 │
│ Memory 1 │ │ Memory 2 │ │ Memory 3 │
└─────────────┘ └─────────────┘ └─────────────┘
^ ^ ^
| | |
└─────────────────────┴───────────────────────┘
Взаимодействие через сеть
Примеры распределённых систем
// 1. Микросервисная архитектура
API Gateway ---> UserService (Node 1)
---> OrderService (Node 2)
---> PaymentService (Node 3)
// 2. Распределённая база данных (шардирование)
DB Shard 1: users 1-1000
DB Shard 2: users 1001-2000
DB Shard 3: users 2001-3000
// 3. Кластер веб-серверов
Load Balancer ---> Tomcat Server 1
---> Tomcat Server 2
---> Tomcat Server 3
Основные проблемы распределённых систем
1. Теорема CAP
Система не может одновременно гарантировать три свойства:
CA (Consistency + Availability)
└─ Все узлы имеют актуальные данные (C)
└─ Система всегда отвечает (A)
└─ Но не работает при разделении сети (нет P)
CP (Consistency + Partition tolerance)
└─ Данные согласованы (C)
└─ Система работает при разделении сети (P)
└─ Но может быть недоступна (нет A)
AP (Availability + Partition tolerance)
└─ Система доступна (A)
└─ Работает при разделении сети (P)
└─ Но может быть временная несогласованность (нет C)
Пример выбора:
- Банки выбирают CP — согласованность важнее доступности
- Социальные сети выбирают AP — доступность важнее идеальной согласованности
2. Отказы и сбои
// Узел может выйти из строя в любой момент
public class RemoteServiceClient {
public String callRemoteService(String url) throws Exception {
try {
// Узел может быть недоступен
return httpClient.get(url);
} catch (ConnectException e) {
// Сеть может быть недоступна
// Другой узел может обработать запрос
return fallbackToOtherNode();
} catch (SocketTimeoutException e) {
// Ответ может прийти с задержкой
return retryWithBackoff();
}
}
}
3. Задержки в сети
Сетевая задержка может быть переменной и непредсказуемой:
// Даже "быстрые" операции имеют задержку
long startTime = System.currentTimeMillis();
String response = remoteService.getData(); // Минимум несколько миллисекунд
long latency = System.currentTimeMillis() - startTime;
// В локальной системе эта операция была бы микросекундной!
4. Синхронизация данных
// Проблема: как синхронизировать состояние между узлами?
public class DistributedCache {
// Node 1 обновляет cache
cache.put("user:123", user1);
// Node 2 имеет старое значение
User user = cache.get("user:123"); // Может быть устаревшим!
}
// Решение: консистентность в конечном итоге (eventual consistency)
public class EventuallyConsistentCache {
// Node 1 публикует событие
eventBus.publish(new UserUpdatedEvent(123, user1));
// Node 2 получает событие и обновляет кэш
@EventListener
public void onUserUpdated(UserUpdatedEvent event) {
cache.put("user:" + event.getUserId(), event.getUser());
}
}
Паттерны и технологии
1. RPC (Remote Procedure Call)
// Вызов функции на удалённом узле
public interface RemoteCalculator {
int add(int a, int b);
}
// Server
public class RemoteCalculatorImpl implements RemoteCalculator {
public int add(int a, int b) {
return a + b;
}
}
// Client
RemoteCalculator calculator = RpcProxy.create(RemoteCalculator.class, "server:9999");
int result = calculator.add(5, 3); // Вызов на удалённом сервере
2. REST API
// Каждый узел предоставляет REST API
@RestController
@RequestMapping("/api")
public class OrderController {
@GetMapping("/orders/{id}")
public Order getOrder(@PathVariable Long id) {
return orderService.findById(id);
}
}
// Другой узел вызывает API
RestTemplate rest = new RestTemplate();
Order order = rest.getForObject("http://service1:8080/api/orders/123", Order.class);
3. Message Queue (очередь сообщений)
// Асинхронное взаимодействие через очередь
// Producer (Node 1)
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void createOrder(Order order) {
// Отправляем событие в очередь
rabbitTemplate.convertAndSend("orders.exchange", "order.created", order);
}
}
// Consumer (Node 2)
@Component
public class OrderEventListener {
@RabbitListener(queues = "order.queue")
public void handleOrderCreated(Order order) {
// Обрабатываем событие асинхронно
emailService.sendConfirmation(order);
}
}
Примеры в Java
Apache Kafka (распределённая потоковая платформа)
public class KafkaProducerExample {
public void publishEvent(String topic, String message) {
KafkaTemplate kafkaTemplate = new KafkaTemplate(producerFactory);
kafkaTemplate.send(topic, message);
}
}
public class KafkaConsumerExample {
@KafkaListener(topics = "events", groupId = "my-group")
public void consume(String message) {
System.out.println("Received: " + message);
}
}
Apache ZooKeeper (координация узлов)
public class ZooKeeperCoordinator {
private ZooKeeper zk;
public void registerService(String serviceName, String serviceUrl)
throws KeeperException, InterruptedException {
String path = "/services/" + serviceName;
zk.create(path, serviceUrl.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
}
public List<String> discoverServices(String serviceName)
throws KeeperException, InterruptedException {
String path = "/services/" + serviceName;
return zk.getChildren(path, true);
}
}
Преимущества и недостатки
Преимущества:
- Масштабируемость горизонтальная
- Отказоустойчивость
- Лучшее использование ресурсов
- Расширяемость
Недостатки:
- Сложность разработки и отладки
- Проблемы с консистентностью данных
- Увеличенная задержка (latency)
- Сложность операций и мониторинга
Распределённые системы — это основа современного масштабируемого ПО, но требуют глубокого понимания их проблем и паттернов решения.