Pull to refresh

Comments 23

Интересно. Я всегда считал, что CAP — это некий общий принцип, который не вдается в частности организации системы, а его интерпретация немножко другая.
Availability — это именно обработка запроса с минимальной задержкой, нежели просто доступность данных. В распределенной системе невозможно одновременно Consistency и Availability по причине того, что для «C» необходим координированный доступ к данным (через блокировки или MVCC), которые в распределенной среде занимают большое время (необходим ответ от всех затронутых нодов). То есть для чтения либо жертвуем «А» и ждем, когда коммитнется транзакция, либо жертвуем «C» и читаем неполные данные (при асинхронной репликации).

Если CAP затрагивает только аспект сетевого fault tolerance, но не latency, то она действительно очень ограничена.

P.S. как я понял, линеаризируемость — это перевод «serializable»?
Я вот тоже до недавнего времени считал, что это общий принцип. Но наткнувшись на статью и почитав ссылки из нее, я понял, что это не так. Я так впечатлился, что решил перевести, потому что это очень важно.

Нет, «линеаризуемость» это не «сериализуемость», это совсем разные термины по статье.
Сериализация представляет собой процесс преобразования объекта в поток байтов для хранения объекта или передачи его в память, базу данных или файл. Ее основное назначение — сохранить состояние объекта для того, чтобы иметь возможность воссоздать его при необходимости. В то время как линеаризация это сохранение строго исторического порядка записей\запросов как они приходили в систему. В каком-то частном случае это может быть одно и то же.

Про Availability в статье тоже есть. И вы правы, что сейчас это относится больше к SLA и измеряется в процентах и по сути является latency.
Линеаризуемость и сериализуемость — разные понятия.

Линеаризуемость — изменения применяются практически мгновенно.
Сериализуемость — результат получается из некоторой последовательности транзакций.

Подробнее здесь
Статья поднимает правильные вопросы, но формулировка идеи чересчур широка. «Забудьте САР теорему как более не актуальную» — сразу же вспоминается институт, где фраза «забудьте всё, чему вас учили в школе» была расхожей, а также первые дни на работе, где часто можно было слышать «забудьте все, чему вас учили раньше».

Это неправильно, и CAP теорема в своё время послужила основанием для обширных исследований и подтолкнула развитие распределенных систем обработки данных. Также введенная ей концепция BASE стала основой для многих реальных систем.

То, что CAP-теорема кем-то неверно трактуется еще не значит, что она более не актуальна. Это равносильно высказыванию «теорема Пифагора более не актуальна» после появления неевклидовой геометрии
Проблема CAP теоремы в том что она ничего по сути не может сказать о базе данных. Это сейчас по большей части маркетинг чушь, типа способы позиционирования себя на рынке для тех кто не в курсе. Ну и CAP теорема эта слишком поверхностна чтоб хоть как-то охарактеризовать базу данных, потому как современные БД не вписываются в нее на таком лобовом уровне. Весь смысл в том чтобы отказаться от CAP теоремы как от способа хоть как-то описывать базы данных в современном мире.
Не совсем согласен с термином «база данных», скорее теорема все-таки говорит о системах обработки данных в общем. Тот же Zookeeper базой данных можно назвать с большой натяжкой.

Сам автор статьи говорит, что он не знает, что лучше использовать для классификации систем обработки данных. С моей точки зрения CAP теорема тем не менее в этом смысле очень хороша, если её правильно использовать. Не «наша система является AP» или «наша система является CP», а «проблема консистентности в нашей системе решается так ...», «проблема доступности в нашей системе решается так ...» — как общее направление рассуждений о характере распределенной системы. Сам автор теоремы убеждает избегать категоричности в классификации систем
Я совсем даже не сварщик, но архитекторы систем должны, по-моему, быть достаточно флегматичными, чтобы не купиться на столь кричащий заголовок.

А для новичков материала горы и категоричность
Забудьте, Прекратите характеризовать
Но чтобы вы ни делали, прекратите.
не нужна, как подметил 0x0FFF.

Вот ещё, апрельское (eng):
lvh — Distributed Systems 101 — PyCon 2015:
A very brief introduction to the theory and practice of distributed systems.
Про базы данных, которые нелинеаризованны, я что-то не очень понял (
Видимо, транзакции теперь тотально запрещены на планете Земля.
Представьте таблицу «table» с одним полем «a», значение которого «1». И такую последовательность действий:
  1. Транзакция1 — начало
  2. Транзакция1 — select a from table
  3. Транзакция2 — начало
  4. Транзакция2 — select a from table
  5. Транзакция1 — update table set a = 2 (значение посчитано во внешней системе как результат select'а + 1)
  6. Транзакция1 — commit
  7. Транзакция2 — update table set a = 2 (значение посчитано во внешней системе как результат select'а + 1)
  8. Транзакция2 — commit

Есть разные уровни изоляции транзакций, и разные модели консистентности (на видео выше их указано 16). Даже если вы выберете serializable, в том же mysql это serializable* (то есть не совсем serializable) и от проблемы указанного выше примера не защитит. В Oracle есть serializable*, который по сути RR, а совсем не serializable. В MS SQL ситуация аналогична, и их serializable* от проблемы в моем примере не защитит. В postgresql есть честный serializable, но эта честность не бесплатна — вторая транзакция при попытке commit упадет с ошибкой, и рестартовать её уже проблема вашего приложения. Также есть разница между serializability, lineralizability и strict serializability (см. здесь и здесь). Если просто, то serializability гарантирует, что «существует» порядок последовательного выполнения транзакций, выполняемых параллельно. Lineralizability же также гарантирует, то этот порядок соответствует порядку инициации транзакций (раньше стартовала — раньше выполнена).
САР — то тут причем? первый коммит должен пройти, второй должен упасть, если Вы требуете тотальной консистентности [ а вот если первый не прошел, то второй может(а не должен) пройти ] (strict consistency), если полная блокировка всей базы не столь принципиальна, можно условия ослабить(и записать любой), но теорема, то тут причем.
Я согласен, что ее применяют не к месту. Исхожу из того, что она всего лишь завуалированная констатация факта, что нельзя сделать быструю, надежную и дешевую систему, чем-то прийдется жертвовать. И когда проектируют систему, то указывают _последовательность_ приоритетов в ее реализации, но дальше… оценивать реализацию системы по соответствию ее заявленым приоритетам, а не свойствам — глупость.
А причем тут транзакции? Как понимаю на картинке master-slave репликация, и изменения тупо еще не поступили на Folower 2.
??? если требовать полной консистентности (С в САР-теореме), то транзакции не могут нормально завершиться если нет подтверждения с обоих (или вернее — всех серверов, поэтому и такие глюки и задержки). А то, что нет такой системы (в топике объясняется почему), которая этот режим реализует — это другой разговор.

Хочется «С» — жди всех соединений, и пусть все остальные отдыхают. Хочется «А» — не надейтесь на согласованность.
Это вы описываете синхронную репликацию.
А какую должен описать?(транзакцию, а репликация это если разработчик так ее реализует)
Транзакция и репликация это две отдельные темы, т.к. репликация может быть синхронной или асинхронной.
В случае асинхронной утверждение
первый коммит должен пройти, второй должен упасть:
ложно.
Последняя фраза моего комментария на который вы отписались (Это вы описываете синхронную репликацию.) как раз это и говорит.
CAP не причем, я ответил на комментарий касающийся параграфа статьи, в котором содержится утверждение, что базы данных не линерализованны. И это действительно так, я показал пример
Вы не правы. В Вашем примере вторая транзакция откатится даже на минимальном уровне (READ_UNCOMMITED). От потерянного обновления защищают все уровни. Говоря иначе, транзакция устанавливает «write-locks» на измененные ею данные, которые также проверяются при записи в других параллельных транзакциях. Проблема как раз с «read-locks»: т.к. 90% операций — чтение, то для быстродействия на разных уровнях ими пренебрегают для быстродействия. Для полностью Serializable уровня необходимы read-блокировки, который каждый реализует как может: кто блокирует таблицу целиком (H2, Derby), Mysql, кажется, просто добавляет в каждый SELECT… FOR UPDATE..., но в целом всегда очень неэффективно.

В современных базах на смену write-блокоровкам пришел более эффективный контроль версий (MVCC), на основе которого очень просто и сразу реализуется т.н. Snapshot-изоляция, которая лежит между Serializable и Repeatable read. Многие производители (Oracle) тупо называют ее Serializable, тогда как другие (MsSQL, Postgres, DB2) имеют специально отдельный уровень для Serializable.

А вот пример, который не выполнится при Serializable, но прокатит при Snapshot (т.н. write skew). У клиента в банке два счета. По контракту его суммарный баланс на всех счетах не должен быть отрицательным, тогда как на любом из счетов он может быть негативный. Пусть на обоих счетах лежат по 50 енотов (A=50, B=50). И на оба счета приходят одновременно две транзакции на 100 енотов (X=100, Y=100):
T1:
select A, B
if (A+B-X < 0) fail
else update A = A-X
T2:
select B, A
if (A+B-Y < 0) fail
else update B = B-Y

Поскольку для параллельных T1 и T2 A+B=100, и записываемые данные не пересекаются, то в результате на обоих счетах у клиента будет по -50 енотов. Эта проблема и многие схожие легко решаются при помощи ручной блокировки (pessimistic lock). Поэтому в большинстве приложений хватает READ_COMMITED уровня, установленного по умолчанию плюс ручное отслеживание схожих ситуаций.
Вы не правы. Потерянное обновление — это если бы команда была «update test set a = a + 1;» в обоих транзакциях, и действительно от неё защищают все уровни изоляции транзакций. Тут вопрос в том, что новое значение для a вычислено во внешней системе, и мой пример выполнится везде, кроме PostgreSQL в режиме serializable, вы можете проверить
Сорри! Действительно! Пару лет назад делал похожие тесты, и вторая транзакция реально откатывалась! Попробовал сейчас повторить — обе коммитаются! Более того, даже если в H2 поставить serializable уровень, обе транзакции прокатывают! Надо будет найти те исходники и посмотреть в чем дело.
Что-то мне не нравится термин «латентность».
Sign up to leave a comment.

Articles