Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Некоторые сценарии, например продажа билетов, вообще невозможны без ACID гарантий.
Нужно поддерживать уникальность пары — (сеанс\рейс, место) в масштабах всей системы.В MongoDB можно поддерживать уникальность.
кто помешает двум параллельным транзакциям на шаге 2 попортить счета?Атомарные операции выполняются последовательно, при обновлении происходит проверка на условия, в итоге операция не пройдет если условие не удовлетворяет.
Кроме того такие «транзакции» требуют чтобы вся запись приходила в одну ноду, иначе две транзакции в разных нодах дадут рассогласованное состояние.Без разницы сколько нод, оно будет Eventual Consistency, так что все нормально.
Короче дока откровенно врет.Вам нужно ознакомиться с инструментом прежде чем делать такие заявления.
Атомарные операции выполняются последовательно, при обновлении происходит проверка на условия, в итоге операция не пройдет если условие не удовлетворяет.
Без разницы сколько нод, оно будет Eventual Consistency, так что все нормально.
Вам нужно ознакомиться с инструментом прежде чем делать такие заявления.
Кстати двух-фазные комиты могут быть эффективнее, например если вся транзакция со счетом занимает 0.5 сек, обычные транзакции будут выполнятся последовательно с одним и тем же счетом занимая 0.5 сек на каждую транзакцию, когда с двух-фазными комитами за эти 0.5 сек может пройти например 100 транзакций параллельно.
Предположим что две транзации пришли в разные ноды, обе списали по $100 c баланса A и перевели на баланс Б.Это не возможная ситуация, потому что «Баланс А» в единственном экземпляре, и находится в одной ноде независимо от того на каких нодах находятся остальные данные (счета, транзакции, и пр. см. шардинг)
монга позиционируется как AP система с eventual consistency… и, как не трудно догадаться — это типичная маркетинговая чушь :)
Нужно поддерживать уникальность пары — (сеанс\рейс, место) в масштабах всей системы.
А зачем для этого ACID, почему недостаточно eventual consistency?
Полное зеркалирование неустойчиво к разделению, увы.
Все билеты данные одного сеанса на одной ноде — вообще не распределенная система. Доступность её равна доступности базы.
Оба варианта дают строгую согласованность с точки зрения CAP.
Напомню что разговор начался с вашего вопроса:
Почему?
Вы забываете, что таких нод может быть бесконечное количество.
В рамках ноды. В рамках системы — eventual consistency.
… в котором я понимал ACID в рамках всей системы, а не одной ноды.
Простой сценарий: два сервера, А и Б. Вся запись идет на A и зеркалируется на Б. Между А и Б прерывается связь, но оба сервера живы и доступны для клиента.
[...]
В этом плане нельзя обмануть CAP, нельзя создать одновременно доступную и согласованную систему при возможности разделений сети.
Если вы начинаете реплицировать данные между нодами, то у вас становится AP система, и появляется проблема как бы не продать два билета на одно место.
Ну и вы сами в итоге предлагаете сделать ACID в рамках всей системы.
Ну так CAP никто и не обманывает. Речь идет о том, что можно обойтись без глобального ACID.
Это почему?
Отнюдь. Операции в рамках системы не атомарны, и именно вся система целиком будет консистентна только в какой-то момент времени.
Если асинхронная, то AP. То есть может быть так что произошла запись на сервер А, но он упал и запись пошла на Б и продали два билета.
Например в тех же кинотеатрах есть программы лояльности, которые позволяют по накопительным картам делать скидки, и все, строго разделить на не пересекающиеся наборы уже не выйдет.
Гарантии нужны только на шаге 2.Например так в монге можно забронировать билет: (для примера, в реальных системах по другому)
db.tickets.findAndModify({ query:{ _id:1, booked:false }, update:{ booked:true } })
В итоге две бронирования одного и того же билета могут выполнится «успешно» в одной и той же ноде.
Но в случае падении ноды после восстановления не гарантированно данные сохранятся, а билет уже продан.Это уже другой вопрос, но и для этого есть решения, например write concern, это позволяет, при обновлении документа, указать (минимальное) кол-во нод, на которые «запишутся» изменения прежде чем документ будет считаться записанным.
например write concern, это позволяет, при обновлении документа, указать (минимальное) кол-во нод, на которые «запишутся» изменения прежде чем документ будет считаться записанным.
Но в случае падении ноды после восстановления не гарантированно данные сохранятся, а билет уже проданДля этого в монге есть журналирование, из доки: «MongoDB uses write ahead logging to an on-disk journal to guarantee write operation durability and to provide crash resiliency.»
Если количество реплик N, а минимальное количество нод, на которые надо записать M, то при любом M<N можно продать два билета на одно место.Если прикинуть что нода падает раз в год (хотя на моей практике, ещё реже), то шанс что 2 ноды упадут в один момент, стремиться к нулю, и этого достаточно (хотя кол-во нод можно поднять).
если при разделении сети нода, на которую пришла запись может достучаться до нод, общем количеством меньше M, то или теряем согласованность записи, или доступностьЕсли сеть «расколется», то будет работать только тот кусок где есть арбитр, остальные куски «встанут» и клиент получит фейл. Тут же можете манипулировать с M, N, т.е. есть варианты.
MongoDB uses write ahead logging to an on-disk journal to guarantee write operation durability and to provide crash resiliency.Это по умолчанию так работает? Помоему даже в текущей версии монга говорит что все ОК сразу после принятия команды и до записи в лог.
Если прикинуть что нода падает раз в год (хотя на моей практике, ещё реже), то шанс что 2 ноды упадут в один момент, стремиться к нулю, и этого достаточно (хотя кол-во нод можно поднять).
Если сеть «расколется», то будет работать только тот кусок где есть арбитр, остальные куски «встанут» и клиент получит фейл. Тут же можете манипулировать с M, N, т.е. есть варианты.Это называется кворум.
А что вы будете делать с *SQL и несколькими нодами?
Это по умолчанию так работает? Помоему даже в текущей версии монга говорит что все ОК сразу после принятия команды и до записи в лог.Это регулируется с помощью «write concern», можете часть команд выполнить «до журнала», часть «после журнала», часть после «репликационной ноды».
Помоему даже в текущей версии монга говорит что все ОК сразу после принятия команды и до записи в лог.Подтверждаю.
А что вы будете делать с *SQL и несколькими нодами?
То есть приложение должно разбираться на сколько нод нужно сохранитьможно настроить дефолтное поведение, а вообще это гибкость, например для логов и комментариев это не обязательно.
А если записи будут приходить на разные ноды? Или все идет только в одну?
Обычно master-slave репликация. При падении мастера выбирается другой мастер.в монге реплика работает подобным образом.
можно настроить дефолтное поведение, а вообще это гибкость, например для логов и комментариев это не обязательно.Отвечу цитатой своего комментария выше:
Ну и опять же, если начинать крутить настройки Монги, чтобы она стала сопоставима по надежности/доступности с чем-то из обычных реляционных БД, то ВНЕЗАПНО оказывается, что Монга начинает работать во много раз медленнее и эти самые традиционные реляционные БД её обгоняют.
Разделение сети — крайне редкое явление в наше время. Гилберт и Личн прямо заявляют, что системы, работающие в локальной сети, можно считать не подверженными разделению.
На практике я ни разу не видел разделения сети. А вы видели?
Вопрос в том, актуальна ли она для «простых смертных». Мы тогда забивали, но было неприятно потом баланс сводить и рефандить недовольных клиентов.то есть у вас была ap система. если не секрет, то что использовалось?
кто-нибудь обязательно вспомнит о CAP-«теореме»Если это вы про мой комментарий в теме про MongoDB, то я-то как раз имел ввиду изначальную формулировку, которая, конечно же, никакая не теорема, а гипотеза, основанная на общих соображениях.
Несколько фактов о CAP-«теореме»