Senior Go Interview Prep - Core Go: https://go.vbloher.org/docs/01-core-go/ - Механика defer в Go: https://go.vbloher.org/docs/01-core-go/defer/ - Встраивание структур и интерфейсов (Embedding): https://go.vbloher.org/docs/01-core-go/embedding/ - Ошибки в Go: error, wrapping, errors.Is/As/Join: https://go.vbloher.org/docs/01-core-go/errors/ - Дженерики в Go (1.18+): https://go.vbloher.org/docs/01-core-go/generics/ - Интерфейсы в Go: https://go.vbloher.org/docs/01-core-go/interfaces/ - Устройство map в Go: https://go.vbloher.org/docs/01-core-go/maps/ - panic / recover: механика, раскрутка стека и runtime-паники: https://go.vbloher.org/docs/01-core-go/panic-recover/ - Указатели в Go: https://go.vbloher.org/docs/01-core-go/pointers/ - Рефлексия в Go (reflect): https://go.vbloher.org/docs/01-core-go/reflection/ - Внутреннее устройство слайсов в Go: https://go.vbloher.org/docs/01-core-go/slices/ - Строки, руны и байты в Go: https://go.vbloher.org/docs/01-core-go/strings-runes-bytes/ - Система типов Go: defined types, alignment, memory layout: https://go.vbloher.org/docs/01-core-go/type-system/ - Concurrency: https://go.vbloher.org/docs/02-concurrency/ - sync/atomic: https://go.vbloher.org/docs/02-concurrency/atomic/ - Буферизованные vs небуферизованные каналы: https://go.vbloher.org/docs/02-concurrency/buffered-unbuffered/ - Канал vs Mutex: когда что выбрать: https://go.vbloher.org/docs/02-concurrency/channel-vs-mutex/ - Каналы: устройство hchan: https://go.vbloher.org/docs/02-concurrency/channels/ - Утечки горутин, дедлоки, livelock, starvation: https://go.vbloher.org/docs/02-concurrency/common-leaks-deadlocks/ - sync.Cond: https://go.vbloher.org/docs/02-concurrency/cond/ - context: https://go.vbloher.org/docs/02-concurrency/context/ - Горутины: жизненный цикл, стоимость, стек: https://go.vbloher.org/docs/02-concurrency/goroutines-lifecycle/ - sync.Mutex и sync.RWMutex: https://go.vbloher.org/docs/02-concurrency/mutex-rwmutex/ - sync.Once: https://go.vbloher.org/docs/02-concurrency/once/ - Паттерны конкурентности: https://go.vbloher.org/docs/02-concurrency/patterns/ - Race Detector (гонки данных и -race): https://go.vbloher.org/docs/02-concurrency/race-detector/ - Планировщик GMP: https://go.vbloher.org/docs/02-concurrency/scheduler-gmp/ - select: https://go.vbloher.org/docs/02-concurrency/select/ - sync.WaitGroup: https://go.vbloher.org/docs/02-concurrency/waitgroup/ - Runtime и память: https://go.vbloher.org/docs/03-runtime-memory/ - Паттерны аллокаций и снижение давления на GC: https://go.vbloher.org/docs/03-runtime-memory/allocation-patterns/ - Escape Analysis: когда переменная убегает в кучу: https://go.vbloher.org/docs/03-runtime-memory/escape-analysis/ - Сборщик мусора Go: concurrent tri-color mark-sweep: https://go.vbloher.org/docs/03-runtime-memory/gc/ - Тюнинг GC: GOGC и GOMEMLIMIT: https://go.vbloher.org/docs/03-runtime-memory/gogc-gomemlimit/ - GOMAXPROCS: параллелизм планировщика и проблема контейнеров: https://go.vbloher.org/docs/03-runtime-memory/gomaxprocs/ - Утечки горутин (goroutine leaks): https://go.vbloher.org/docs/03-runtime-memory/goroutine-leaks/ - Утечки памяти в Go (несмотря на GC): https://go.vbloher.org/docs/03-runtime-memory/memory-leaks/ - Модель памяти Go (Go Memory Model): happens-before и синхронизация: https://go.vbloher.org/docs/03-runtime-memory/memory-model/ - pprof: профилирование CPU, памяти и блокировок в Go: https://go.vbloher.org/docs/03-runtime-memory/pprof/ - Execution Tracer и runtime/trace: тайминги вместо агрегатов: https://go.vbloher.org/docs/03-runtime-memory/runtime-tracing/ - Стек vs Куча: где живут данные в Go: https://go.vbloher.org/docs/03-runtime-memory/stack-vs-heap/ - Тестирование: https://go.vbloher.org/docs/04-testing/ - testify, assert/require и golden files: https://go.vbloher.org/docs/04-testing/assertions-testify/ - Бенчмарки в Go: https://go.vbloher.org/docs/04-testing/benchmarks/ - Покрытие, -race и флаки-тесты: https://go.vbloher.org/docs/04-testing/coverage-race/ - Нативный fuzzing в Go (1.18+): https://go.vbloher.org/docs/04-testing/fuzzing/ - Интеграционные тесты, testcontainers-go, TestMain: https://go.vbloher.org/docs/04-testing/integration-testcontainers/ - Моки, стабы и тестируемость: https://go.vbloher.org/docs/04-testing/mocks/ - Table-driven тесты, subtests и параллельность: https://go.vbloher.org/docs/04-testing/table-driven/ - Backend: https://go.vbloher.org/docs/05-backend/ - Аутентификация и авторизация: AuthN/AuthZ, сессии vs токены, RBAC/ABAC, API keys, mTLS, секреты: https://go.vbloher.org/docs/05-backend/auth-authz/ - Graceful Shutdown HTTP/gRPC сервера в Go: https://go.vbloher.org/docs/05-backend/graceful-shutdown/ - gRPC: типы RPC, интерсепторы, контекст, метаданные, error model: https://go.vbloher.org/docs/05-backend/grpc/ - JWT (JSON Web Token): https://go.vbloher.org/docs/05-backend/jwt/ - Middleware-паттерн в Go: https://go.vbloher.org/docs/05-backend/middleware/ - net/http: Server, Handler, ServeMux, таймауты, Client и контекст: https://go.vbloher.org/docs/05-backend/net-http/ - OAuth2: роли, grant types, OIDC, токены и типовые ошибки: https://go.vbloher.org/docs/05-backend/oauth2/ - OpenAPI/Swagger, code generation, contract-first vs code-first, валидация: https://go.vbloher.org/docs/05-backend/openapi/ - Protocol Buffers: схемы, wire format, эволюция и совместимость: https://go.vbloher.org/docs/05-backend/protobuf/ - REST: принципы, версионирование, идемпотентность, статусы, пагинация, ошибки: https://go.vbloher.org/docs/05-backend/rest/ - Сети и протоколы: https://go.vbloher.org/docs/06-networking/ - Пулы соединений: http.Transport, БД, утечки: https://go.vbloher.org/docs/06-networking/connection-pooling/ - DNS: записи, резолвинг, кэширование, DNS в Go: https://go.vbloher.org/docs/06-networking/dns/ - Версии HTTP: 1.1, 2, 3: https://go.vbloher.org/docs/06-networking/http-versions/ - TCP/IP: модель, транспорт и что важно бэкендеру: https://go.vbloher.org/docs/06-networking/tcp-ip/ - TLS: handshake, сертификаты, mTLS, производительность: https://go.vbloher.org/docs/06-networking/tls/ - UDP и надёжность поверх UDP: https://go.vbloher.org/docs/06-networking/udp/ - WebSocket: upgrade, фреймы, масштабирование: https://go.vbloher.org/docs/06-networking/websocket/ - Базы данных: https://go.vbloher.org/docs/07-databases/ - Пул соединений к PostgreSQL в Go: database/sql, pgx, pgxpool, PgBouncer: https://go.vbloher.org/docs/07-databases/connection-pooling-pgx/ - Взаимоблокировки (Deadlocks) в PostgreSQL: https://go.vbloher.org/docs/07-databases/deadlocks/ - Индексы в PostgreSQL: https://go.vbloher.org/docs/07-databases/indexes/ - Уровни изоляции транзакций в PostgreSQL: https://go.vbloher.org/docs/07-databases/isolation-levels/ - MVCC в PostgreSQL: версии строк, видимость, VACUUM и bloat: https://go.vbloher.org/docs/07-databases/mvcc/ - Обзор NoSQL и Redis: https://go.vbloher.org/docs/07-databases/nosql-redis/ - Партиционирование таблиц в PostgreSQL: https://go.vbloher.org/docs/07-databases/partitioning/ - Архитектура PostgreSQL: https://go.vbloher.org/docs/07-databases/postgresql-architecture/ - Планирование и оптимизация запросов в PostgreSQL: https://go.vbloher.org/docs/07-databases/query-planning/ - Репликация в PostgreSQL: https://go.vbloher.org/docs/07-databases/replication/ - Шардирование (горизонтальное масштабирование): https://go.vbloher.org/docs/07-databases/sharding/ - Транзакции в PostgreSQL и Go (database/sql, pgx): https://go.vbloher.org/docs/07-databases/transactions/ - Распределённые системы: https://go.vbloher.org/docs/08-distributed-systems/ - CAP теорема: https://go.vbloher.org/docs/08-distributed-systems/cap-theorem/ - Circuit Breaker: https://go.vbloher.org/docs/08-distributed-systems/circuit-breaker/ - Консенсус и Raft: репликация состояния в присутствии отказов: https://go.vbloher.org/docs/08-distributed-systems/consensus-raft/ - Модели согласованности: https://go.vbloher.org/docs/08-distributed-systems/consistency/ - Гарантии доставки сообщений: at-most-once / at-least-once / exactly-once: https://go.vbloher.org/docs/08-distributed-systems/delivery-guarantees/ - Eventual Consistency: https://go.vbloher.org/docs/08-distributed-systems/eventual-consistency/ - Идемпотентность в распределённых системах: https://go.vbloher.org/docs/08-distributed-systems/idempotency/ - Apache Kafka: https://go.vbloher.org/docs/08-distributed-systems/kafka/ - Transactional Outbox: https://go.vbloher.org/docs/08-distributed-systems/outbox/ - RabbitMQ: AMQP 0-9-1, маршрутизация, надёжность доставки и сравнение с Kafka: https://go.vbloher.org/docs/08-distributed-systems/rabbitmq/ - Ретраи: backoff, jitter, budgets и идемпотентность: https://go.vbloher.org/docs/08-distributed-systems/retries/ - Saga Pattern: https://go.vbloher.org/docs/08-distributed-systems/saga/ - Observability: https://go.vbloher.org/docs/09-observability/ - Grafana: https://go.vbloher.org/docs/09-observability/grafana/ - Метрики: RED, USE, Golden Signals: https://go.vbloher.org/docs/09-observability/metrics/ - OpenTelemetry: https://go.vbloher.org/docs/09-observability/opentelemetry/ - Prometheus: https://go.vbloher.org/docs/09-observability/prometheus/ - SLI / SLO / SLA: https://go.vbloher.org/docs/09-observability/slo-sli/ - Структурированное логирование (slog): https://go.vbloher.org/docs/09-observability/structured-logging/ - Distributed Tracing: https://go.vbloher.org/docs/09-observability/tracing/ - System Design: https://go.vbloher.org/docs/10-system-design/ - Analytics Pipeline: https://go.vbloher.org/docs/10-system-design/analytics-pipeline/ - Chat System: https://go.vbloher.org/docs/10-system-design/chat/ - Фреймворк System Design интервью: https://go.vbloher.org/docs/10-system-design/framework/ - Notification Service: https://go.vbloher.org/docs/10-system-design/notification-service/ - Order Service: https://go.vbloher.org/docs/10-system-design/order-service/ - Payment Service: https://go.vbloher.org/docs/10-system-design/payment-service/ - Rate Limiter: https://go.vbloher.org/docs/10-system-design/rate-limiter/ - URL Shortener: https://go.vbloher.org/docs/10-system-design/url-shortener/ - DevOps: https://go.vbloher.org/docs/11-devops/ - CI/CD: пайплайны, стадии, стратегии деплоя: https://go.vbloher.org/docs/11-devops/cicd/ - Облака (AWS / GCP) для бэкендера: https://go.vbloher.org/docs/11-devops/cloud-aws-gcp/ - Docker для Go-разработчика: https://go.vbloher.org/docs/11-devops/docker/ - GitHub Actions и GitLab CI: https://go.vbloher.org/docs/11-devops/github-gitlab-ci/ - Kubernetes для Go-разработчика: https://go.vbloher.org/docs/11-devops/kubernetes/ - Terraform / Infrastructure as Code: https://go.vbloher.org/docs/11-devops/terraform/ - Алгоритмы: https://go.vbloher.org/docs/12-algorithms/ - Типовые алгоритмические задачи и паттерны: https://go.vbloher.org/docs/12-algorithms/common-problems/ - Асимптотическая сложность (Big-O): https://go.vbloher.org/docs/12-algorithms/complexity/ - Структуры данных в Go: https://go.vbloher.org/docs/12-algorithms/data-structures/ - Специфика live-coding на Go: https://go.vbloher.org/docs/12-algorithms/go-specifics/ - Behavioral: https://go.vbloher.org/docs/13-behavioral/ - Конфликты, разногласия и работа со стейкхолдерами: https://go.vbloher.org/docs/13-behavioral/conflicts/ - Как проходит senior-интервью: этапы, оценка, оффер: https://go.vbloher.org/docs/13-behavioral/interview-flow/ - Лидерство и менторство: https://go.vbloher.org/docs/13-behavioral/leadership-mentoring/ - Типовые поведенческие вопросы для Senior: https://go.vbloher.org/docs/13-behavioral/senior-questions/ > Модуль: Распределённые системы · Уровень: Senior+ ## TL;DR - CAP — это **не** «выбери 2 из 3». Сетевые партиции (P) случаются вне твоего контроля, поэтому реальный выбор делается **только во время партиции**: либо Consistency, либо Availability. В отсутствие партиции можно иметь и C, и A одновременно. - **C** в CAP — это **linearizability** (строгая согласованность по чтению, recency guarantee), а **не** буква C из ACID (consistency = соблюдение инвариантов/констрейнтов). Это разные понятия, которые путают чаще всего. - **A** в CAP — это «каждый запрос к работающему узлу получает (не-error) ответ». Это очень жёсткое определение: latency не учитывается, ответ должен прийти от любой ноды, не упавшей физически. - **P (partition tolerance)** — система продолжает работать при потере произвольного числа сообщений между узлами. Для распределённой системы это не опция, а данность. - **CP**: при партиции жертвуем доступностью (некоторые узлы отвечают ошибкой/таймаутом ради согласованности). Примеры: etcd, ZooKeeper, Consul, HBase, Spanner, традиционные RDBMS с синхронной репликацией. - **AP**: при партиции жертвуем линеаризуемостью (узлы отвечают возможно устаревшими данными). Примеры: Cassandra, DynamoDB, Riak, Voldemort. - **PACELC** дополняет CAP: при **P**artition выбираем между **A**/**C**, иначе (**E**lse) — между **L**atency/**C**onsistency. Это честнее описывает реальные системы. ## Теория ### Формулировка и её точный смысл Теорему сформулировал Эрик Брюер (2000, conjecture), формально доказали Gilbert & Lynch (2002). Точная формулировка доказанной версии: > В асинхронной сетевой модели невозможно реализовать read/write регистр, который одновременно гарантирует **linearizability** (C) и **availability** (A) при наличии **partition** (P). Ключевые определения из статьи Gilbert & Lynch: - **Consistency (atomic / linearizable)**: должна существовать единая total order над всеми операциями такая, что каждая операция выглядит атомарно выполненной в один момент времени; чтение возвращает результат последней завершившейся записи (по реальному времени). Это и есть **linearizability**. - **Availability**: каждый запрос, полученный неупавшим узлом, должен завершиться (вернуть **успешный** ответ, не ошибку). Важно: нет ограничения на время — но «вернуть ошибку» или «бесконечно ждать» не считается доступностью. - **Partition tolerance**: сеть может терять произвольное количество сообщений, отправленных от одного узла другому. ### Почему «2 из 3» — заблуждение Формулировка «выбери 2 из 3» подразумевает, что CA-система (без partition tolerance) — легитимный выбор. Но: 1. **P нельзя «выключить»**. Партиции — свойство сети, а не дизайна. Кабель оборвётся, GC-пауза заморозит ноду на 10 секунд, switch перегрузится. Вы не выбираете, случится ли партиция; вы выбираете, как себя вести, когда она случилась. 2. **CA без P бессмысленна в распределённой системе**. «CA» в практике означает «однонодовая система» (или система, которая просто упадёт/потеряет данные при партиции). Это не третий вариант, это отказ от распределённости. Поэтому корректная ментальная модель: **P — это данность, а реальный выбор — C vs A только в момент партиции.** ``` Партиция случилась? ┌──────────────┴──────────────┐ НЕТ ДА можно C И A выбор: C ИЛИ A (PACELC: тут ┌──────┴───────┐ выбор L vs C) CP AP (ошибки/ (stale таймауты, reads, но consistent) но доступно) ``` ### C в CAP ≠ C в ACID Это самая частая путаница на собеседованиях. | | CAP «C» | ACID «C» | |---|---|---| | Что значит | Linearizability — чтение видит самую свежую запись, единый порядок операций | Транзакция переводит БД из одного валидного состояния в другое (инварианты, FK, constraints, триггеры) | | Про что | Согласованность **между репликами/во времени** | Согласованность **относительно прикладных правил** | | Кто обеспечивает | Протокол репликации/консенсуса | Приложение (определяет инварианты) + БД (энфорсит constraints) | Можно иметь ACID-C без linearizability (single-node БД с констрейнтами) и наоборот. В CAP под C понимается строго recency-гарантия чтения. ### Что значит «availability» во время партиции Рассмотрим партицию, разрезавшую систему на две группы узлов {A, B} | {C, D}. Клиент обращается к узлу A. - **CP-выбор**: A понимает, что не может связаться с большинством (или не уверен, что у него актуальные данные), и **отвечает ошибкой/таймаутом**. Система отдала availability, но любой ответ, который она *всё-таки* даёт, линеаризуем. Пример: запись в etcd на узле меньшинства провалится, потому что Raft требует кворума. - **AP-выбор**: A **отвечает данными**, которые у него есть локально, даже если на стороне {C, D} уже была более свежая запись. Система доступна, но чтение может быть устаревшим (нарушение linearizability). Пример: Cassandra с `CL=ONE` вернёт значение с доступной реплики. Заметьте: «доступность» в CAP — это про возврат **успешного** ответа от каждого работающего узла. Реальные «highly available» системы в маркетинге часто имеют в виду не это (а, скажем, 99.99% uptime), что добавляет путаницы. ### Кворумы: не бинарный выбор На практике системы настраиваются по осям через кворумы. Для N реплик с W (write quorum) и R (read quorum): - Если **W + R > N** — гарантируется пересечение множеств read/write реплик ⇒ строгая согласованность по чтению (при отсутствии конкурентных записей и read-repair-аномалий). - Если **W + R ≤ N** — возможны stale reads, зато выше доступность и ниже latency. Dynamo-style системы (Cassandra, Riak) позволяют выбирать это **на каждый запрос**: одна и та же система может вести себя как «более CP» (`QUORUM`/`ALL`) или «более AP» (`ONE`) в зависимости от consistency level. Поэтому ярлык «AP-система» — упрощение: это про *дефолт* и *возможности*. ``` N=3, W=2, R=2 → W+R=4 > 3 → пересечение гарантировано (strong-ish read) N=3, W=1, R=1 → W+R=2 ≤ 3 → возможен stale read (AP-режим) ``` ### PACELC CAP молчит про поведение **в нормальном режиме** (без партиций). Daniel Abadi предложил PACELC (2010): > **if (P) then choose A or C; ELSE choose L (latency) or C (consistency).** Идея: даже без партиций есть фундаментальный трейдофф между низкой задержкой и сильной согласованностью. Чтобы дать линеаризуемое чтение, надо синхронно дотянуться до кворума/лидера — это latency. Чтобы быть быстрым — читаем с ближайшей реплики, рискуя устаревшими данными. Классификация (Abadi): | Система | При партиции (PAC) | В норме (ELC) | Ярлык | |---|---|---|---| | Dynamo / Cassandra / Riak | A (доступность) | L (низкая задержка) | PA/EL | | Spanner | C | C | PC/EC (за счёт TrueTime) | | ZooKeeper / etcd | C | C (читает с лидера/кворума)\* | PC/EC | | MongoDB (по дефолту) | C (отказ записи без primary) | L (чтение с secondary) | PC/EL | | PNUTS (Yahoo) | C | L | PC/EL | \* etcd/ZK могут отдавать линеаризуемые чтения через лидера или быстрые «локальные» чтения с риском staleness — настраивается. PACELC объясняет, почему две «CP-системы» могут вести себя по-разному в обычной жизни, и почему Spanner (PC/EC) платит latency-цену за глобальную согласованность. ### Примеры систем **CP (consistency > availability при партиции):** - **etcd** — Raft, требует кворум (N/2+1). Узлы меньшинства не обслуживают записи и (по умолчанию) линеаризуемые чтения. Используется как source of truth для Kubernetes. - **ZooKeeper** — Zab-протокол; запись требует кворума; при потере кворума ансамбль перестаёт обслуживать записи. (Нюанс: чтения по умолчанию могут быть слегка устаревшими — ZK гарантирует не полную линеаризуемость чтений, а sequential consistency + sync().) - **Consul** — Raft для каталога/KV. - **HBase** — каждый регион обслуживается ровно одним RegionServer; при его недоступности регион недоступен до failover (strong consistency, жертвует availability). - **Spanner** — синхронная репликация через Paxos + TrueTime, даёт external consistency (strict serializability); при партиции узлы меньшинства недоступны. **AP (availability > consistency при партиции):** - **Cassandra** — Dynamo-style, tunable consistency, hinted handoff, read-repair, last-write-wins по timestamp. По дефолту склонна к доступности. - **DynamoDB** — eventually consistent reads по умолчанию (есть опция strongly consistent read, которая стоит дороже и менее доступна). - **Riak** — Dynamo-style, vector clocks для разрешения конфликтов, sibling values. ### Доказательство-интуиция (на пальцах) Два узла G1 и G2, партиция между ними. Клиент пишет v2 в G1, затем читает с G2. - Если G2 **отвечает** (availability) — он не мог узнать про v2 (сообщения теряются), вернёт v1 ⇒ нарушена linearizability (C). - Если G2 хочет сохранить C — он должен **дождаться** синхронизации с G1, которая невозможна при партиции ⇒ либо ждёт вечно, либо отвечает ошибкой ⇒ нарушена availability (A). Нельзя одновременно ответить успешно и ответить свежими данными ⇒ C и A несовместимы при P. ## Подводные камни / gotchas - **«CA-система»** — почти всегда маркетинг или непонимание. В распределённой системе P неизбежна; «CA» = «мы не пережили партицию». - **Путаница C (CAP) и C (ACID).** Если на собеседовании спрашивают «PostgreSQL — это CP или AP?», корректный ответ требует уточнения топологии (одна нода? синхронная/асинхронная репликация?), и нельзя смешивать ACID-консистентность с линеаризуемостью. - **Ярлык «AP/CP» вешают на систему целиком**, хотя многие системы tunable per-request (Cassandra CL, Dynamo consistent read, MongoDB read/write concern). Точнее говорить про конфигурацию. - **Availability в CAP ≠ uptime/SLA.** CAP-availability — формальное «каждый живой узел отвечает успехом». 99.99% доступности из SLA — другое. - **CAP — модель read/write регистра**, она не охватывает транзакции над несколькими объектами, latency, durability, согласованность реплик при отсутствии партиции — поэтому в реальном проектировании опираются на PACELC и конкретные consistency models. - **Партиция ≠ только обрыв сети.** Долгая GC-пауза, перегруженный диск, медленный сосед — для протокола неотличимы от партиции (узел «пропал»). Это влияет на тюнинг таймаутов. - **«Eventually consistent» не значит «несогласованная всегда».** Это значит, что при прекращении записей реплики сойдутся; во время записей возможны аномалии. ## Вопросы на собеседовании **В:** Почему «выбери 2 из 3» — неправильная трактовка CAP? **О:** Потому что P (partition tolerance) — не дизайн-решение, а свойство сети: партиции случаются независимо от вас. Реальный выбор — C vs A, и только в момент партиции. Вне партиции можно иметь и C, и A. «CA-система» на практике означает однонодовую систему, которая просто не переживёт партицию. **В:** Что именно означает буква C в CAP? **О:** Linearizability — строгая согласованность по чтению: существует единый порядок всех операций по реальному времени, и чтение возвращает результат самой последней завершившейся записи. Это recency-гарантия, а не ACID-консистентность (соблюдение инвариантов/констрейнтов). **В:** Чем C в CAP отличается от C в ACID? **О:** CAP-C — про согласованность между репликами во времени (linearizability). ACID-C — про то, что транзакция оставляет БД в валидном состоянии относительно прикладных инвариантов и констрейнтов. Можно иметь одно без другого. Single-node БД даёт ACID-C, но к CAP-C отношения не имеет. **В:** Что значит «availability» в CAP-смысле? **О:** Каждый запрос к неупавшему узлу завершается успешным (не-error) ответом. Нет ограничения на время, но возврат ошибки или таймаут — это уже не availability. Это жёстче, чем бытовое «система работает». **В:** Как кворумы соотносятся с выбором C/A? **О:** Для N реплик при W+R>N read- и write-кворумы пересекаются, что даёт строгую согласованность по чтению (склон к CP). При W+R≤N возможны stale reads, зато выше доступность и ниже задержка (склон к AP). Dynamo-style системы позволяют выбирать это на каждый запрос. **В:** Что добавляет PACELC к CAP? **О:** PACELC описывает поведение и в нормальном режиме: «if Partition then A or C, Else then Latency or C». То есть даже без партиций есть трейдофф между низкой задержкой и сильной согласованностью. Это объясняет, почему, например, Spanner (PC/EC) платит latency за глобальную согласованность, а Cassandra (PA/EL) выбирает скорость. **В:** К какому классу отнести Cassandra и почему это упрощение? **О:** По дефолту PA/EL (доступность и низкая задержка). Но Cassandra tunable: с `CL=QUORUM`/`ALL` она ведёт себя ближе к CP. Поэтому ярлык описывает дефолт и склонность, а не жёсткое свойство — фактическое поведение задаётся consistency level на запрос. **В:** etcd — CP или AP? Что происходит с узлом в меньшинстве при партиции? **О:** CP. etcd использует Raft и требует кворум большинства. Узел в меньшинстве не может коммитить записи и не обслуживает линеаризуемые чтения — он вернёт ошибку/таймаут. Система жертвует доступностью этой части ради согласованности. **В:** Может ли долгая GC-пауза вызвать поведение как при партиции? **О:** Да. Для протокола узел, замерший на STW-паузе, неотличим от пропавшего из-за обрыва сети: он перестаёт отвечать на heartbeat, его могут исключить из кворума/переизбрать лидера. Поэтому партиции — это не только физический обрыв, и таймауты надо тюнить с учётом GC. ## На что копают на senior+ - Умение **развести CAP-C и ACID-C** без подсказок и привести пример системы, у которой есть одно, но нет другого. - Понимание, что **P не опциональна**, и способность переформулировать любой вопрос «AP или CP?» в «как система ведёт себя в момент партиции». - Знание **PACELC** и умение классифицировать реальные системы по обеим осям (Spanner PC/EC, Dynamo PA/EL, MongoDB PC/EL). - Понимание **tunable consistency** через кворумы (W+R>N), и того, что один кластер может работать в разных режимах per-request. - Точное определение **availability** по Gilbert & Lynch и осознание, что это не про uptime/SLA. - Знание ограничений модели: CAP — про **один read/write регистр**, не про мульти-объектные транзакции, durability и latency; для них нужны другие модели (linearizability vs serializability, PACELC). - Практические следствия для архитектуры: где ставить **source of truth** (часто CP — etcd/ZK для конфигурации/leader election), а где терпеть eventual consistency ради доступности (корзина, лента, метрики).