← Назад к вопросам

Что такое CAP теорема?

2.7 Senior🔥 121 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

CAP теорема

CAP теорема (теорема Брюэра) — это фундаментальный принцип распределённых систем, утверждающий, что невозможно одновременно гарантировать три желаемых свойства. Аббревиатура CAP расшифровывается как:

  • C (Consistency) — согласованность данных
  • A (Availability) — доступность сервиса
  • P (Partition Tolerance) — устойчивость к разделению сети

Определение каждого свойства

Согласованность (Consistency)

Все клиенты видят одни и те же данные в один момент времени. После записи значения, все последующие чтения должны вернуть это обновлённое значение (даже при наличии нескольких копий данных).

# Пример: распределённая кэш система
# Когда мы обновляем значение в основной хранилище,
# все узлы должны видеть актуальное значение
value = cache.get("user:123")
if value is None:
    value = db.get("user:123")
    cache.set("user:123", value)
return value

Доступность (Availability)

Система всегда доступна и отвечает на запросы. Любой работающий узел должен ответить на запрос в разумное время, без гарантии того, что ответ содержит самые свежие данные.

# Пример: система с репликацией
# Даже если один узел недоступен, система продолжает работать
for replica in replicas:
    try:
        return replica.get_data(key)
    except ConnectionError:
        continue
raise ServiceUnavailableError()

Устойчивость к разделению (Partition Tolerance)

Система продолжает функционировать при разделении сети (network partition), когда узлы не могут общаться друг с другом. Это свойство необходимо в любой распределённой системе и обычно считается обязательным.

Компромиссы CAP

Теорема постулирует, что из трёх свойств можно выбрать только два:

CP (Consistency + Partition Tolerance)

Гарантируется согласованность и устойчивость к разделению, но система может быть недоступна:

  • Примеры: Google Bigtable, HBase, MongoDB (в некоторых режимах)
  • Поведение при разделении: система блокирует запись, пока не будет восстановлена связь
class CPDatastore:
    def write(self, key, value):
        if not self.is_connected_to_master():
            raise UnavailableError("Cannot guarantee consistency")
        self.replicate_to_all_nodes(key, value)

AP (Availability + Partition Tolerance)

Гарантируется доступность и устойчивость к разделению, но нарушается согласованность:

  • Примеры: DynamoDB, Cassandra, Riak
  • Поведение при разделении: система продолжает работать с локальными копиями, позже синхронизирует данные (eventual consistency)
class APDatastore:
    def write(self, key, value):
        # Всегда доступна для записи
        self.local_write(key, value)
        # Попробуем отправить на другие узлы
        try:
            self.async_replicate(key, value)
        except ConnectionError:
            # Синхронизируем позже
            self.queue_for_sync(key, value)

CA (Consistency + Availability)

Гарантируется согласованность и доступность, но система не переживёт разделение сети. На практике невозможно в распределённой системе:

  • Примеры: традиционные реляционные БД с одним сервером

Практическое применение

import redis
from typing import Any

class ConsistentCache:
    """CP: Согласованный кэш с синхронной репликацией"""
    def __init__(self, primary_redis, replica_redis):
        self.primary = primary_redis
        self.replica = replica_redis
    
    def set(self, key: str, value: Any):
        # Пишем в обе копии или не пишем вообще
        self.primary.set(key, value)
        self.replica.set(key, value)
    
    def get(self, key: str) -> Any:
        return self.primary.get(key)

class EventuallyConsistentCache:
    """AP: Кэш с асинхронной репликацией (eventual consistency)"""
    def __init__(self, primary_redis, replica_redis):
        self.primary = primary_redis
        self.replica = replica_redis
    
    def set(self, key: str, value: Any):
        # Всегда доступны для записи
        self.primary.set(key, value)
        try:
            self.replica.set(key, value)
        except:
            # Синхронизируем потом через очередь задач
            queue_sync_task(key, value)
    
    def get(self, key: str) -> Any:
        # Можем вернуть устаревшие данные
        return self.primary.get(key)

В контексте Python разработки

  1. Выбор БД: Понимание CAP теоремы помогает выбрать подходящую БД для проекта
  2. Кэширование: При использовании Redis/Memcached нужно понимать компромиссы
  3. Микросервисы: Распределённые системы требуют выбора между CP и AP
  4. Обработка ошибок: Нужна стратегия для работы при сетевых разделениях

Важное уточнение

Современная интерпретация (PACELC теорема) уточняет CAP: если произойдёт разделение сети (P), выбираем между согласованностью (C) и доступностью (A). Если разделения нет (else), выбираем между задержкой (L) и согласованностью (C).

Что такое CAP теорема? | PrepBro