Этот текст является вольным переводом замечательного поста Kaushik Sathupadi на тему распределённых систем и существующих ограничений при их создании.
При разработке распределённых систем вы наверняка часто услышите упоминания об CAP-теореме. Давайте попробуем понять её через ситуацию, которая могла возникнуть в реальной жизни.
Вчера, когда ваша супруга в очередной раз оценила тот факт, что вы вспомнили о её дне рождения и подарили шикарный подарок, в голове всплыла забавная идея. «Хм, а ведь люди вечно всё забывают». А у вас просто блестящая память! Почему бы не сделать новый сервис, который позволит полностью раскрыться вашему таланту? С каждой мыслью об этой идее вам всё больше и больше она нравится. Вы уже даже придумали рекламу, которую можно было бы напечатать в газете:
Типичное обращение в ваш сервис выглядело бы вот так:
Прошло несколько месяцев...
Ура, дело пошло! Ваша идея настолько проста, насколько эффективна. Сервис выстреливает, вы получаете сотни заказов каждый день.
Всё бы хорошо, но появилась проблема: всё больше и больше клиентов ждёт своей очереди поговорить с вами. Некоторые не выдерживают ожидания и просто бросают трубку. Более того: когда вы заболели и не могли работать, пропал целый день бизнеса и вся выручка. И это ещё не говоря о неудовлетворённых клиентах, потерявших возможность получить информацию. Решено — пора расширяться! Возьмём супругу в помощь.
Итак, план простой:
Вы очень взволнованы этой идеей, ведь:
Шикарно! Это же распределённая система! И почему все эти ребята, делающие софт, так шумят по поводу распределённых систем, всё же так просто!
Всё идёт по плану, до того как…
Через два дня после внедрения новой системы вы получаете звонок от вашего постоянного клиента, Ивана Андреевича:
Через день Иван Андреевич снова звонит вам:
Как это вообще могло произойти? Может Иван Андреевич просто наврал? Вы размышляете о том, что случилось, и вам в голову врезается мысль. Может быть Иван Андреевич позвонил вашей жене? Вы находите её записную книжку, и, о да, как вы и предполагали, на страничке Ивана Андреевича указано то, что он должен был уехать в Нью-Йорк вчера.
Какой ужасный изъян вашей, казалось бы, прекрасной схемы! Ваша распределённая система не согласована! Всегда есть шанс того, что клиент сообщит что-то вам или вашей жене, а следующим звонком он попадёт к другому человеку, который не будет в курсе последних изменений.
Ваши конкуренты могли бы спокойно игнорировать плохое обслуживание, но вы, конечно, заботитесь о своих клиентах и репутации. Пока ваша жена спала, вам не давала покоя проблема, вы всю ночь думали и пытались найти выход и ситуации. Бинго! Когда жена проснулась, вы в тот же момент ей говорите о новых планах:
Вы замечаете единственную проблему — вы не можете работать параллельно. Каждый раз, когда вам звонит коллега для синхронизации, вы не можете отвечать на звонки клиентов — вы будете заняты. Но это не так уж и страшно, ведь большинство звонков поступает с просьбами что-то напомнить (поиск), а не что-то запомнить (обновление).
Главное — ответить клиенту правильно любой ценой.
«Отлично», говорит вам супруга, «Однако есть ещё одна брешь, о которой ты не подумал. Что, если в один прекрасный день кто-то не сможет выйти на работу? Тогда у нас не получится принять ни единой просьбы запомнить, ведь другой человек не сможет записать изменения в свою записную книжку. Это, братец, у нас получается проблема доступности, так как, к примеру, если запрос на обновление придёт ко мне, я не смогу завершить звонок клиента: даже если я записала изменения в свою записную книжку, у меня не выйдет записать их в твою. Таким образом, я не смогу попрощаться с клиентом!»
Вы уже осознали, почему распределённые системы не такие простые, как вы думали. Сложно ли придумать решение, которое было бы одновременно «доступно и согласовано»? Кто-нибудь может и сдался, но не вы! Ваши конкуренты и не мечтали о том, что вы придумали. И вновь вы нетерпеливо будите свою жену…
«Смотри, это то, что нам нужно для доступности и согласованности.» План почти такой же, как в прошлый раз, но с важными изменениями:
Гениально! Вы не можете найти ни одного недостатка в получившемся решении. Теперь «Позвони, напомню» одновременно доступный и согласованный сервис.
Кажется, всё отлично уже который день. Ваша система согласована. Всё работает, даже если кто-то из вас не может выйти на работу. Но что выйдет, если вы оба вышли на работу, но один из вас не может обновить информацию другого? Помните, как вы будили свою жену с очередным Гениальнейшим Бредом? Что, если ваша жена решится принимать звонки, но будет слишком обижена на вас и решит не разговаривать с вами весь день? Весь ваш бизнес опять превратится в тыкву! Ваша идея до сих пор хороша за её согласованность и доступность, но очень чувствительна к разделению коммуникаций! Вы конечно, можете не принимать ни одного звонка, пока вы в ссоре, но тогда ваша система будет недоступна всё это время…
Итак, давайте теперь взглянем на CAP-теорему. Утверждается, что при разработке распределённой системы вы не можете достичь одновременно трёх свойств: доступность, согласованность и терпимость к разделению сети. Вы можете выбрать только два из:
Вот вам ещё один повод поразмыслить. Вы можете нанять курьера. Он будет обновлять вашу или записную книжку супруги в тот момент когда изменилась информация в другой книжке. Самая большая выгода от подобного подхода в том, что он может работать в «фоновом режиме» и чьё-либо обновление ни блокирует другого человека для того, чтобы обновиться. Таким образом работает множество NoSQL решений, одна нода локально обновляет себя и фоновый процесс синхронизирует остальные ноды соответственно. Единственная проблема заключается в том, что теряется согласованность на некоторое время. Например, клиент звонит вашей жене и до того момента, пока курьер добежит до вас, он перезванивает и попадает на линию к вам. Как видите, он получит несогласованный ответ. Но всё равно, это остаётся отличной идеей, если подобные случаи ограниченны. Например, наши клиенты не страдают амнезией и не забывают то, о чём они сообщили 5 минут назад.
Я постарался объяснить вам CAP-теорему и Eventually Consistency простым, доступным языком. С радостью приму ваши вопросы, замечания и комментарии.
При разработке распределённых систем вы наверняка часто услышите упоминания об CAP-теореме. Давайте попробуем понять её через ситуацию, которая могла возникнуть в реальной жизни.
Часть №1: Идея нового сервиса — «Позвони, напомню!»
Вчера, когда ваша супруга в очередной раз оценила тот факт, что вы вспомнили о её дне рождения и подарили шикарный подарок, в голове всплыла забавная идея. «Хм, а ведь люди вечно всё забывают». А у вас просто блестящая память! Почему бы не сделать новый сервис, который позволит полностью раскрыться вашему таланту? С каждой мыслью об этой идее вам всё больше и больше она нравится. Вы уже даже придумали рекламу, которую можно было бы напечатать в газете:
«Позвони, напомню» — Никогда не забывайте, даже если вы не помните, что забыли!
Плохо себя чувствуете из-за того, что вы что-то забыли? Не переживайте. Помощь на расстоянии одного телефонного звонка!
Если вам нужно что-то запомнить, просто позвоните и сообщите нам об этом! Допустим, позвоните нам и сообщите телефон вашего босса. Забудьте про него. Когда вам нужно будет вспомнить его, перезвоните, и мы вам обязательно напомним.
Всего 3 рубля за звонок.
Типичное обращение в ваш сервис выглядело бы вот так:
- Клиент: — Привет, не могли бы вы запомнить День Рождения моего соседа?
- Вы: — Конечно, какое число?
- Клиент: — Второго января.
- Вы: — (Записываете дату в записную книжку) Всё, записали. Звоните нам в любой момент, когда вам что-то понадобится.
- Клиент: — Кстати, мне тут пришла идея, что ему стоило бы подарить радиоуправляемый вертолёт, он обожает такие штуки!
- Вы: — Отличная идея для подарка, мы обязательно вам её напомним.
- Клиент: — Спасибо!
- Вы: — Всегда пожалуйста, с вашего счёта снято 3 рубля.
Прошло несколько месяцев...
- Клиент: — Привет, кажется я что-то забыл...
- Вы: — Добрый день, конечно, пару секунд… (Ищем страничку клиента в записной книжке)
- Вы: — Спасибо, что подождали. Через неделю день рождения вашего соседа, не забудьте его поздравить и подарить радиоуправляемую модель вертолёта.
- Клиент: — Точно, спасибо огромное! И подарок супер, как вы догадались?
- Вы: Всегда рады помочь, с вашего счёта снято 3 рубля.
Часть 2: Бизнес растёт
Ура, дело пошло! Ваша идея настолько проста, насколько эффективна. Сервис выстреливает, вы получаете сотни заказов каждый день.
Всё бы хорошо, но появилась проблема: всё больше и больше клиентов ждёт своей очереди поговорить с вами. Некоторые не выдерживают ожидания и просто бросают трубку. Более того: когда вы заболели и не могли работать, пропал целый день бизнеса и вся выручка. И это ещё не говоря о неудовлетворённых клиентах, потерявших возможность получить информацию. Решено — пора расширяться! Возьмём супругу в помощь.
Итак, план простой:
- Вручаем вам и жене по дополнительному телефону.
- Клиенты продолжают звонить по тому же номеру: нет необходимости запоминать несколько номеров.
- АТС перенаправляет звонки клиентов тому, кто в данный момент свободен.
Вы очень взволнованы этой идеей, ведь:
- Можно обслуживать в два раза больше клиентов.
- Если даже кто-то заболеет и не сможет работать, сервис не останавливается и продолжает функционировать.
Шикарно! Это же распределённая система! И почему все эти ребята, делающие софт, так шумят по поводу распределённых систем, всё же так просто!
Всё идёт по плану, до того как…
Часть 3: Первый провал
Через два дня после внедрения новой системы вы получаете звонок от вашего постоянного клиента, Ивана Андреевича:
- Иван: — Добрый день.
- Вы: — Здравствуйте, «Позвони, напомню!», чем мы можем вам помочь?
- Иван: — Напомните, пожалуйста, я ничего там не забыл?
- Вы: — Секунду… (смотрите в записную книжку, но на страничке Ивана Андреевича нет ничего того, о чём стоило бы напомнить)
- Вы: — Нет, всё отлично, вы ни о чём не забыли, Иван Андреевич!
- Иван: — Замечательно, спасибо большое.
Через день Иван Андреевич снова звонит вам:
- Иван: — Вы меня сильно подвели, у вас ужасный сервис. У меня была запланирована командировка в Нью-Йорк по важным делам, а я пропустил самолёт. И главное, я просил вас напомнить, но нет, вы наврали. Я очень зол. (гудки)
- Вы: — Но как...
Как это вообще могло произойти? Может Иван Андреевич просто наврал? Вы размышляете о том, что случилось, и вам в голову врезается мысль. Может быть Иван Андреевич позвонил вашей жене? Вы находите её записную книжку, и, о да, как вы и предполагали, на страничке Ивана Андреевича указано то, что он должен был уехать в Нью-Йорк вчера.
Какой ужасный изъян вашей, казалось бы, прекрасной схемы! Ваша распределённая система не согласована! Всегда есть шанс того, что клиент сообщит что-то вам или вашей жене, а следующим звонком он попадёт к другому человеку, который не будет в курсе последних изменений.
Часть 4: Решаем проблему согласованности
Ваши конкуренты могли бы спокойно игнорировать плохое обслуживание, но вы, конечно, заботитесь о своих клиентах и репутации. Пока ваша жена спала, вам не давала покоя проблема, вы всю ночь думали и пытались найти выход и ситуации. Бинго! Когда жена проснулась, вы в тот же момент ей говорите о новых планах:
- Когда кому-либо из вас звонит клиент и хочет что-нибудь запомнить, до того, как сказать «Спасибо, мы всё записали» вы звоните другому человеку и сообщаете о изменениях.
- Таким образом, у вас обоих записаны все последние обновления.
- Когда клиент звонит для того, что бы напомнить себе что-нибудь, вам не надо звонить супруге — у вас всегда при себе вся правильная и актуальная информация.
Вы замечаете единственную проблему — вы не можете работать параллельно. Каждый раз, когда вам звонит коллега для синхронизации, вы не можете отвечать на звонки клиентов — вы будете заняты. Но это не так уж и страшно, ведь большинство звонков поступает с просьбами что-то напомнить (поиск), а не что-то запомнить (обновление).
Главное — ответить клиенту правильно любой ценой.
«Отлично», говорит вам супруга, «Однако есть ещё одна брешь, о которой ты не подумал. Что, если в один прекрасный день кто-то не сможет выйти на работу? Тогда у нас не получится принять ни единой просьбы запомнить, ведь другой человек не сможет записать изменения в свою записную книжку. Это, братец, у нас получается проблема доступности, так как, к примеру, если запрос на обновление придёт ко мне, я не смогу завершить звонок клиента: даже если я записала изменения в свою записную книжку, у меня не выйдет записать их в твою. Таким образом, я не смогу попрощаться с клиентом!»
Часть 5: К вам приходит Гениальнейшая Идея
Вы уже осознали, почему распределённые системы не такие простые, как вы думали. Сложно ли придумать решение, которое было бы одновременно «доступно и согласовано»? Кто-нибудь может и сдался, но не вы! Ваши конкуренты и не мечтали о том, что вы придумали. И вновь вы нетерпеливо будите свою жену…
«Смотри, это то, что нам нужно для доступности и согласованности.» План почти такой же, как в прошлый раз, но с важными изменениями:
- Когда кому-либо из вас звонит клиент и хочет что-нибудь запомнить, до того, как сказать «Спасибо, мы всё записали» вы проверяете, доступен ли коллега и, если доступен, звоните другому человеку и сообщаете о изменениях.
- Если коллега не доступен, то вы пишете письмо на электронную почту с информацией об новых обновлениях.
- Первым делом после отсутствия на работе вы или супруга проверяете почту и записываете изменения перед тем, как принимать звонки.
Гениально! Вы не можете найти ни одного недостатка в получившемся решении. Теперь «Позвони, напомню» одновременно доступный и согласованный сервис.
Часть 6: Супруги иногда ссорятся
Кажется, всё отлично уже который день. Ваша система согласована. Всё работает, даже если кто-то из вас не может выйти на работу. Но что выйдет, если вы оба вышли на работу, но один из вас не может обновить информацию другого? Помните, как вы будили свою жену с очередным Гениальнейшим Бредом? Что, если ваша жена решится принимать звонки, но будет слишком обижена на вас и решит не разговаривать с вами весь день? Весь ваш бизнес опять превратится в тыкву! Ваша идея до сих пор хороша за её согласованность и доступность, но очень чувствительна к разделению коммуникаций! Вы конечно, можете не принимать ни одного звонка, пока вы в ссоре, но тогда ваша система будет недоступна всё это время…
Часть 7: Выводы
Итак, давайте теперь взглянем на CAP-теорему. Утверждается, что при разработке распределённой системы вы не можете достичь одновременно трёх свойств: доступность, согласованность и терпимость к разделению сети. Вы можете выбрать только два из:
- Согласованность (Consistency) — Ваши клиенты единожды обновив информацию всегда могут получить самые актуальные данные при их последующем запросе. И не важно, насколько быстро они вам перезвонят.
- Доступность (Availability) — «Позвони, напомню» всегда доступна для звонков в тот момент, когда хотя бы один из сотрудников вышел на работу.
- Терпимость к разделению сети. (Partition Tolerance) «Позвони, напомню» всегда работает корректно, даже если вы потеряли связь с вашей женой.
Бонус: достигаем доступности со временем с помощью курьера.
Вот вам ещё один повод поразмыслить. Вы можете нанять курьера. Он будет обновлять вашу или записную книжку супруги в тот момент когда изменилась информация в другой книжке. Самая большая выгода от подобного подхода в том, что он может работать в «фоновом режиме» и чьё-либо обновление ни блокирует другого человека для того, чтобы обновиться. Таким образом работает множество NoSQL решений, одна нода локально обновляет себя и фоновый процесс синхронизирует остальные ноды соответственно. Единственная проблема заключается в том, что теряется согласованность на некоторое время. Например, клиент звонит вашей жене и до того момента, пока курьер добежит до вас, он перезванивает и попадает на линию к вам. Как видите, он получит несогласованный ответ. Но всё равно, это остаётся отличной идеей, если подобные случаи ограниченны. Например, наши клиенты не страдают амнезией и не забывают то, о чём они сообщили 5 минут назад.
Я постарался объяснить вам CAP-теорему и Eventually Consistency простым, доступным языком. С радостью приму ваши вопросы, замечания и комментарии.