Суть Читай реальные конфиги, опции запросов и сценарий разделения; предскажи поведение CP/AP и гарантию согласованности, которую каждый из них реально покупает.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min
Выбор CAP/PACELC не абстрактен — он живёт в уровнях согласованности, write concern и настройках кворума. Прочитай каждый конфиг, затем предскажи, как он поведёт себя при разделении.
Цель
Отработай движение, которое делаешь на каждом design review: переведи конфиг уровня согласованности или кворума в его конкретное поведение CP/AP и точную гарантию, которую он даёт читателю во время разделения.
-- N = 3 реплики на ключ (replication factor 3)CONSISTENCY QUORUM; -- W и R требуют по 2 из 3 подтвержденийINSERT INTO orders (id, total) VALUES (?, ?);SELECT total FROM orders WHERE id = ?;
Викторина
Completed
При RF=3 и QUORUM (W=2, R=2) какую гарантию даёт W+R > N и как разделение меняет позицию системы?
Heads-up Cassandra — AP только на низкой согласованности (например ONE). На QUORUM она требует 2 из 3 подтверждений; разделение, оставляющее координатор с одной репликой, проваливает операцию — это CP-поведение для этого запроса.
Heads-up Пересечение от W+R > N — это и есть гарантия против устаревания: кворум чтения обязан пересечь самый недавний кворум записи, поэтому наблюдается свежее значение. Долговечность — отдельная забота.
Heads-up Пересечение кворумов даёт строгую согласованность на ключ для этих чтений/записей, но не полную линеаризуемость по всем ключам или для конкурентных обновлений. Две конкурентные записи QUORUM всё равно могут гонкой пересечься; их разрешает LWW.
Сниппет 2 — write/read concern в MongoDB
db.accounts.updateOne( { _id: id }, { $inc: { balance: -100 } }, { writeConcern: { w: 1 } } // подтверждение только от primary);// в другом месте, сервис отчётности:db.accounts.find({ _id: id }).readPreference("secondaryPreferred");
Викторина
Completed
Какую опасность для согласованности создаёт эта связка и какое исправление даёт наибольший рычаг?
Heads-up По умолчанию согласованность есть только для чтений с primary при majority concern. Здесь w:1 плюс чтение с secondary явно отказываются от этого: secondary может отставать, а w:1-запись не majority-долговечна и теряется при failover.
Heads-up w:1 быстрее именно потому, что пропускает ожидание репликации — это и есть источник риска корректности (устаревшие чтения с secondary и откат при failover), а не просто ручка задержки.
Heads-up Чтения с primary чинят устаревшее чтение с secondary, но w:1-запись всё ещё лежит только на primary и может быть откачена, если этот primary упадёт до репликации. Нужна w:majority для долговечности при failover.
Сниппет 3 — лог сценария разделения
12:00:01 region=us-east PUT cart/42 -> 200 OK (локальная запись принята)12:00:01 region=eu-west PUT cart/42 -> 200 OK (локальная запись принята)12:00:02 link us-east<->eu-west: 100% потеря пакетов (разделение)12:03:10 link восстановлен; начинается anti-entropy примирение12:03:10 cart/42 имеет две расходящиеся версии, равные siblings по векторным часам
Викторина
Completed
Оба PUT вернули 200 во время разделения. Что это говорит о хранилище и что должно произойти при примирении?
Heads-up CP-хранилище отклонило бы одну сторону во время разделения, чтобы избежать расхождения. Возврат 200 на обеих сторонах — это выбор AP, и получившимся siblings нужно явное разрешение конфликта, а не тихое само-исцеление.
Heads-up Это конкурентные (равные по векторным часам) siblings; LWW отбросил бы корзину одного пользователя на основе дрейфа часов. Конкурентным обновлениям нужно настоящее слияние (объединить товары корзины) или выбор клиента, а не подбрасывание монетки по метке.
Heads-up То, что обе прошли, — это причина конфликта, а не аргумент против него. Независимый приём на обеих сторонах разделения — ровно то, как возникает расхождение в AP-системе.
Сниппет 4 — конфиг кворума Raft/etcd
# Кластер etcd из 3 узлов, один узел в удалённом DCcluster: - { name: n1, dc: primary } - { name: n2, dc: primary } - { name: n3, dc: remote } # высоколатентный канал к primary DCelection-timeout: 1000msheartbeat-interval: 100ms
Викторина
Completed
Удалённый канал к n3 часто скачет выше 1000 мс RTT. Какой режим сбоя провоцирует эта конфигурация и каково исправление?
Heads-up Живучесть Raft зависит от прихода heartbeat в пределах election timeout. RTT выше этого таймаута заставляет здоровый-но-медленный узел запускать разрушительные перевыборы — высокая задержка ведёт себя как разделение.
Heads-up Снижение таймаута ниже джиттера канала делает ложные выборы чаще, а не реже. Таймаут должен сидеть с запасом выше худшего RTT, чтобы избежать флапа.
Heads-up Добавление медленного голосующего ухудшает ситуацию: размер кворума растёт, а нестабильный удалённый узел всё равно запускает выборы. Держи голосующих быстрыми и рядом; сделай удалённый узел неголосующим learner.
Итог
Каждое решение CAP/PACELC проявляется как ручка: W+R > N покупает пересечение для read-your-writes, но становится CP при разделении; w:1 плюс чтения с secondary тихо отказываются от долговечности и свежести; два 200 во время разделения — сигнатура AP, чьим siblings нужно настоящее слияние, а не LWW; а election timeout Raft ниже худшего RTT фабрикует логические разделения. Прочитай конфиг, назови гарантию, которую он реально даёт, затем проверь, как он деградирует при обрыве канала.