Распределенным системам приходится решать вопрос о том, какие именно гарантии доставки поддерживать. У нас есть различные варианты, начиная от отсутствия гарантии и заканчивая гарантией exactly once (точно один раз). В зависимости от того, какой вариант мы выберем, это может повлиять на качество наших потоков данных. В этой статье мы рассмотрим различные гарантии доставки на примере телепортации. "Корабль Тесея" — это мысленный эксперимент, в котором ставится вопрос: Если заменить все части корабля новыми компонентами, останется ли он тем же самым судном? Этот вопрос часто возникает, когда люди обсуждают идею телепортации в научной фантастике. Однако, давайте уточним. Мы не говорим о телепортации, которая пробивает дыру в пространстве и времени, позволяя человеку просто шагнуть через нее. Вместо этого мы обсуждаем телепортацию, при которой человек дематериализуется атом за атомом, а затем вновь материализуется в новом месте. Продолжая рассуждения о "Корабле Тесея", возникает вопрос: Если мы заменим каждый атом человека совершенно новыми, то, по сути, мы его убили и заменили клоном? В этой статье мы не будем пытаться разобраться с вопросом о "Корабле Тесея". Вместо этого мы хотим подойти к идее телепортации с помощью другого, но потенциально связанного с ней мысленного эксперимента, известного как "Проблема двух генералов". Схема решения "Проблемы двух генералов" довольно проста. Два генерала находятся по разные стороны от врага. Они расположились каждый в глубине своей долины, и единственным способом связи является отправка гонцов через вражескую территорию. Эти гонцы могут попасть в плен или погибнуть. Поэтому они ненадежны. Оба генерала возглавляют армии, каждая из которых уступает в численности противнику. Если каждый из них будет атаковать врага в одиночку, то гарантированно потерпит поражение. Они могут добиться успеха, только координируя свои атаки. Надежная связь является ключом к такой координации. Давайте назовем наших генералов Кирк и Пикард. Представьте, что Кирк отправляет Пикарду сообщение, в котором говорится, что они должны атаковать в полдень. Нет никакой гарантии, что гонец прибудет. Однако Кирк не хочет атаковать, не будучи уверенным, что Пикард будет там, чтобы поддержать его.  Для решения этой проблемы Кирк может запросить подтверждение. Когда Пикард получит сообщение, он отправит своего гонца обратно Кирку, чтобы сообщить о своем согласии со временем. Это звучит достаточно просто. Только вот подтверждение должно пересечь вражескую территорию и может затеряться. Это означает, что Пикард не будет знать, получил ли Кирк сообщение. Он не может быть уверен, что Кирк нападет в назначенное время. Единственный способ быть уверенным - запросить еще одно подтверждение, которое снова должно пересечь вражеские границы. Это ставит и Кирка, и Пикара в затруднительное положение. Ни один из них не может быть уверен, что другой получил все их сообщения. Сколько бы подтверждений вы ни отправили, всегда нужно еще хотя бы одно. Другими словами, вы не можете полностью устранить риск. Это подчеркивает нашу основную проблему: если вы общаетесь по ненадежному каналу, то не можете дать гарантии того, что сообщение будет доставлено. Теперь вернемся к научной фантастике. Вопрос заключается в том, использует ли в ней телепортация надежный механизм связи. Очевидно, что это во многом зависит от конкретного произведения. Но в целом можно сказать, что ответ обычно отрицательный. Мы видели примеры, когда корабли, пытающиеся использовать телепортацию, вынуждены идти на крайние меры, чтобы пробиться сквозь воздействие местного излучения. Иногда им приходится отправлять десант, потому что сигнал не может проникнуть через атмосферу планеты. Во всех видах фантастики встречаются примеры, когда неисправность телепортации приводит к тому, что люди становится копиями или даже объединяются с другими объектами и существами. Правда заключается в том, что ненадежная коммуникация способствует созданию интересных сюжетов. Таким образом, хотя в некоторых художественных произведениях может быть предложена новая наука, обеспечивающая хорошую связь, часто это не так. Вопрос в том, каковы последствия этой неопределенности? Предположим, Пикард решает послать своего первого офицера Уилла на поверхность неизвестной планеты. Эта планета испускает странное излучение, которое мешает сигналу. Что должен сделать Пикард? Один из вариантов - приложить максимум усилий. Начинается телепортация, и Пикард молится, чтобы Уилл благополучно прибыл на планету. Телепортер дематериализует его на одном конце (мертв ли он в этот момент?), а затем пытается материализовать вновь уже в пункте назначения (все ли это тот же Уилл?). Но помните, что канал связи ненадежен. Нет никакой гарантии, что Уилл прибыл в пункт назначения. Если у него не получилось, и мы ничего с этим не сделаем, то Уилл исчезнет, затерявшись в потоке данных телепортации. Так что же должен делать Пикар? Логичный ответ - послать Уиллу подтверждение, что он благополучно прибыл. Если будет получено соответствующее сообщение, то поток данных можно будет очистить, и телепортация завершится. Вот только есть еще это досадное излучение, мешающее подтверждению. Если оно не придет, то Пикард не узнает, в безопасности Уилл или нет. В случае, когда он предположит, что Уилл в безопасности, и затем обнаружит, что ошибся, значит, Уилл мертв, потому что телепортация не удалась. Теперь Пикард может предположить, что Уилл не добрался до планеты, и попытаться рематериализовать его обратно на корабль. Таким образом, если телепортация не удалась, Уилл не умрет. Но с другой стороны, если телепортация прошла успешно, то в итоге мы получим две копии Уилла, одну на планете, а другую на корабле. Очевидно, что ни один из вариантов никуда не годится. Одно из возможных решений - продолжать повторять попытки до тех пор, пока телепортация не увенчается успехом.  Если подтверждение не получено, телепортация повторяется. Данные в потоке могут быть использованы для повторного запуска операции. Это можно повторять до тех пор, пока не будет получен сигнал, свидетельствующий об успешности телепортации. Теоретически, остается вероятность того, что это никогда не удастся, и тогда бедняга Уилл снова окажется в телепортационном лимбе. В таком случае, вероятно, Пикард мог бы установить максимум пять попыток, и если все они провалятся, Уилл рематериализуется обратно на корабль. Но это создает две проблемы (или гораздо больше). Помните, ненадежная связь идет в обе стороны. Мы не знаем, получилось или нет у Уилла телепортироваться, или если все-таки это удалось, то он не смог отправить подтверждение. Если телепортация не удалась, нет никакого вреда в повторной попытке, но если она прошла успешно, все становится сложнее. В этом случае при повторных попытках создаются дубликаты Уилла, либо его копии сливаются воедино, поскольку они телепортируются в одно и то же место несколько раз. В результате на планете будет пять копий Уилла, либо одна, напоминающая что-то из фильма ужасов. К тому же, если максимальное число повторных попыток будет превышено, то на корабле будет создана шестая копия Уилла. Это определенно не то, что искали Пикард и Уилл. Так что же им делать? Что им действительно нужно, так это гарантия того, что телепортация удалась один и только один раз. Не должно быть никаких сомнений. К сожалению, "Проблема двух генералов" показывает, что такой уровень уверенности невозможен при использовании ненадежного канала связи. В этом случае остается надеяться на применение логики дедупликации. Другими словами, продолжайте выполнять телепортацию до тех пор, пока она не увенчается успехом, соглашаясь с тем, что она будет создавать дубликаты. Затем разобраться с этими дубликатами. Проблема здесь в том, что работа с дубликатами - дело муторное. По сути, вам нужно убить все копии, кроме одной. Если Пикард ранее не убивал Уилла, просто телепортировав его, то теперь он определенно будет убит. Так этична ли телепортация? Есть три возможных исхода: Принять тот факт, что иногда телепорты не справляются, в результате чего погибает предполагаемый член экипажа Принять, что телепортация гарантированно будет успешной до тех пор, пока вы готовы рискнуть созданием нескольких копий экипажа Принять, что для того, чтобы избежать создания нескольких копий, вы должны быть готовы убить все дубликаты Очевидно, что ни один из этих вариантов не является идеальным. Вы или сознательно убиваете людей, либо намеренно создаете их дубликаты. Попадание на звездолет сопряжено с риском, и экипаж должен быть готов принять его. Но, пожалуй, риск можно уменьшить. Например, возможно, Пикарду не стоит пытаться телепортировать Уилла на планету со странным излучением. Может быть, телепортер должен просто прервать работу, если обнаружит хоть малейшую вероятность неудачи. Это было бы слишком простым решением, но гораздо более полезным для Уилла и остальных членов экипажа. В современной разработке программного обеспечения это не является проблемой. До технологии телепортации еще далеко. Но разработчики каждый день сталкиваются с реальностью "Проблемы двух генералов". Современные сети ненадежны. Каждый раз, когда по ним передается сообщение, существует вероятность сбоя. Это ставит разработчиков перед тем же выбором, который необходимо сделать при телепортации. Они могут принять риск потери сообщений, либо признать, что сообщения будут дублироваться, или найти способ обработки дубликатов.  В мире программного обеспечения это редко является этической дилеммой. Дублирование сообщений обычно не приводит к смерти человека. Но бывают случаи, когда решить такой вопрос становится сложнее. Финансовые операции представляют большую опасность в случае их дублирования или потери. Чтобы этого не произошло, необходимо проявить максимальную осторожность. Аналогично, медицинское устройство, предназначенное для выдачи доз лекарств пациенту, может привести к смерти, если доза будет потеряна или продублирована, причем дозу нельзя отменить. В таких ситуациях разработчики должны быть очень внимательны, чтобы убедиться, что сообщения принимаются нужное количество раз. Возможно, им придется принять соответствующее морально-этическое решение о том, как поступить в случае неожиданного сбоя. В заключение приглашаем всех желающих на открытое занятие по оптимизации  параметров запуска приложения Spark. На нем мы обсудим: Признаки ошибочной конфигурации приложения Spark. Базовые настройки, влияющие на производительность приложения Spark. Ganglia — как инструмент мониторинга кластера для определения узких мест работы приложения Spark. Записаться на открытый урок можно на странице курса "Spark Developer".  Редактор