Формулировка
CAP теорема (теорема Брюера, 2000) утверждает, что распределённая система может обеспечить только два из трёх свойств одновременно:
- C (Consistency) -- согласованность: каждое чтение возвращает результат последней записи
- A (Availability) -- доступность: каждый запрос получает ответ (не ошибку)
- P (Partition Tolerance) -- устойчивость к разделению сети
Почему только 2 из 3
Сетевые разделения (partition) неизбежны. Поэтому P -- обязательное свойство. Выбор сводится к: CP или AP.
Клиент A --> [Узел 1] [Узел 2] <-- Клиент B
РАЗРЫВ СЕТИ
Клиент A записал x=1 на Узел 1.
Клиент B читает x с Узла 2.
CP: Узел 2 отвечает ошибкой (не может гарантировать актуальность)
AP: Узел 2 отвечает старым значением x=0 (доступность важнее)
CP vs AP системы
CP (Consistency + Partition Tolerance)
Система предпочитает ошибку, чем устаревшие данные.
Примеры: ZooKeeper, etcd, MongoDB (write concern majority), HBase
Когда выбирать: финансовые операции, координация (locks), inventory management
AP (Availability + Partition Tolerance)
Система всегда отвечает, даже если данные устаревшие.
Примеры: Cassandra, DynamoDB, CouchDB, DNS
Когда выбирать: соцсети, метрики, корзина покупок, CDN
Таблица выбора
| Система | Тип | Примечание |
|---|---|---|
| PostgreSQL (single) | CA | Нет partition (одноузловая) |
| PostgreSQL + replicas | CP | Зависит от настройки |
| Redis Sentinel | CP | Downtime при failover |
| Cassandra | AP | Tunable consistency |
| MongoDB | CP | Write concern majority |
| Elasticsearch | AP | Split-brain возможен |
| etcd | CP | Raft consensus |
Tunable Consistency
Некоторые системы позволяют выбирать компромисс per-query.
<?php
declare(strict_types=1);
/**
* Tunable consistency levels.
* Strong consistency: R + W > N (read + write replicas > total replicas).
*/
final class TunableConsistency
{
/**
* @return array<string, array{read: int, write: int, consistency: string, use_case: string}>
*/
public static function levels(int $replicas = 3): array
{
$quorum = (int) ceil(($replicas + 1) / 2);
return [
'ONE_ONE' => [
'read' => 1,
'write' => 1,
'consistency' => 'eventual (R+W < N)',
'use_case' => 'Metrics, logs, non-critical data',
],
'QUORUM_QUORUM' => [
'read' => $quorum,
'write' => $quorum,
'consistency' => 'strong (R+W > N)',
'use_case' => 'Most applications, good default',
],
'ALL_ONE' => [
'read' => $replicas,
'write' => 1,
'consistency' => 'strong (N+1 > N)',
'use_case' => 'Write-heavy workloads',
],
'ONE_ALL' => [
'read' => 1,
'write' => $replicas,
'consistency' => 'strong (1+N > N)',
'use_case' => 'Read-heavy workloads',
],
];
}
}
- Partition -- не выбор: разделения случаются, вопрос -- что делать при них
- Не бинарный выбор: можно быть "немного" C и "немного" A
- Partition -- редкость: большую часть времени система может быть и C, и A
- Consistency в CAP != ACID: CAP-consistency -- линеаризуемость, ACID -- целостность данных
- Не учитывает latency: CAP говорит о correctness, не о скорости
Для более полной картины: используйте PACELC теорему, которая учитывает latency vs consistency tradeoff в нормальном режиме работы.
Практическое применение
<?php
declare(strict_types=1);
/**
* Decision framework for choosing CP vs AP.
*/
final class ConsistencyDecision
{
/**
* @return array{model: string, reason: string, systems: string[]}
*/
public static function recommend(
bool $financial,
bool $global,
int $staleTolerance,
): array {
if ($financial) {
return [
'model' => 'CP',
'reason' => 'Financial operations require strong consistency',
'systems' => ['PostgreSQL + sync replication', 'CockroachDB'],
];
}
if ($global && $staleTolerance > 5) {
return [
'model' => 'AP with tunable consistency',
'reason' => 'Global reach + latency needs AP; strong for critical paths',
'systems' => ['DynamoDB', 'Cassandra LOCAL_QUORUM'],
];
}
return [
'model' => 'CP with read replicas',
'reason' => 'Consistency for writes, tolerate stale reads',
'systems' => ['PostgreSQL + read replicas', 'MongoDB replica set'],
];
}
}
- CAP теорема: из C, A, P можно выбрать только два, и P обязателен
- CP: консистентность важнее доступности (финансы, координация)
- AP: доступность важнее консистентности (соцсети, метрики)
- Tunable consistency позволяет выбирать компромисс per-query
- CAP -- полезная модель, но упрощает реальность
- Для полной картины используйте PACELC теорему