<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Yeputons</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Yeputons"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Yeputons"/>
		<updated>2026-08-03T23:04:05Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71630</id>
		<title>Raft</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71630"/>
				<updated>2019-06-04T08:04:46Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Raft''' — алгоритм для решения задачи [[Replicated State Machine]].&lt;br /&gt;
В отличие от [[Paxos]] он не опускает деталей: помимо решения [[Консенсус в распределённой системе|задачи консенсуса]] подробно описывает и выбор лидера, и синхронизацию журнала операций между репликами.&lt;br /&gt;
&lt;br /&gt;
Также одна из целей Raft — быть понятным.&lt;br /&gt;
Можно прочитать [http://blog.egrik.ru/2015/10/raft.html беглое описание на русском], посмотреть [http://thesecretlivesofdata.com/raft/ интерактивную презентацию] для введения и посмотреть [https://raft.github.io/ официальный сайт] (с визуализацией и возможностью поиграться) и [https://raft.github.io/raft.pdf исходную статью] (там чётко выписано состояние процессов, все сообщения и правила).&lt;br /&gt;
&lt;br /&gt;
В визуализации точкой помечен &amp;lt;code&amp;gt;matchIndex[]&amp;lt;/code&amp;gt; (лидер знает, что до этого места лог follower'а совпадает с логом лидера), а стрелочкой — &amp;lt;code&amp;gt;nextIndex[]&amp;lt;/code&amp;gt; (что лидер попробует прислать follower'у).&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Состояние узлов ===&lt;br /&gt;
=== Выбор лидера ===&lt;br /&gt;
=== Репликация логов ===&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71629</id>
		<title>Raft</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71629"/>
				<updated>2019-06-04T07:44:38Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Raft''' — алгоритм для решения задачи [[Replicated State Machine]].&lt;br /&gt;
В отличие от [[Paxos]] он не опускает деталей: помимо решения [[Консенсус в распределённой системе|задачи консенсуса]] подробно описывает и выбор лидера, и синхронизацию журнала операций между репликами.&lt;br /&gt;
&lt;br /&gt;
Также одна из целей Raft — быть понятным.&lt;br /&gt;
Можно прочитать [http://blog.egrik.ru/2015/10/raft.html беглое описание на русском], посмотреть [http://thesecretlivesofdata.com/raft/ интерактивную презентацию] для введения и посмотреть [https://raft.github.io/ официальный сайт] (с визуализацией и возможностью поиграться) и [https://raft.github.io/raft.pdf исходную статью] (там чётко выписано состояние процессов, все сообщения и правила).&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Состояние узлов ===&lt;br /&gt;
=== Выбор лидера ===&lt;br /&gt;
=== Репликация логов ===&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71628</id>
		<title>Raft</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71628"/>
				<updated>2019-06-04T07:43:25Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Raft''' — алгоритм для решения задачи [[Replicated State Machine]].&lt;br /&gt;
В отличие от [[Paxos]] он не опускает деталей: помимо решения [[Консенсус в распределённой системе|задачи консенсуса]] подробно описывает и выбор лидера, и синхронизацию журнала операций между репликами.&lt;br /&gt;
&lt;br /&gt;
Можно прочитать [http://blog.egrik.ru/2015/10/raft.html беглое описание], посмотреть [http://thesecretlivesofdata.com/raft/ интерактивную презентацию] для введения и посмотреть [https://raft.github.io/ официальный сайт] (с визуализацией и возможностью поиграться).&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Состояние узлов ===&lt;br /&gt;
=== Выбор лидера ===&lt;br /&gt;
=== Репликация логов ===&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71627</id>
		<title>Raft</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71627"/>
				<updated>2019-06-04T07:41:23Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Raft''' — алгоритм для решения задачи [[Replicated State Machine]].&lt;br /&gt;
В отличие от [[Paxos]] он не опускает деталей: помимо решения [[Консенсус в распределённой системе|задачи консенсуса]] подробно описывает и выбор лидера, и синхронизацию журнала операций между репликами.&lt;br /&gt;
&lt;br /&gt;
Можно прочитать [http://blog.egrik.ru/2015/10/raft.html беглое описание], посмотреть [http://thesecretlivesofdata.com/raft/ интерактивную презентацию] для введения и посмотреть [https://raft.github.io/ официальный сайт] (с визуализацией и возможностью поиграться).&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Выбор лидера ===&lt;br /&gt;
=== Репликация логов ===&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71626</id>
		<title>Raft</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Raft&amp;diff=71626"/>
				<updated>2019-06-04T07:26:31Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: Новая страница: «Категория:Параллельное программирование '''Raft''' — алгоритм для решения задачи Replicated S…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Raft''' — алгоритм для решения задачи [[Replicated State Machine]].&lt;br /&gt;
В отличие от [[Paxos]] он не опускает деталей: помимо решения [[Консенсус в распределённой системе|задачи консенсуса]] подробно описывает и выбор лидера, и синхронизацию журнала операций между репликами.&lt;br /&gt;
&lt;br /&gt;
Можно прочитать [http://blog.egrik.ru/2015/10/raft.html беглое описание], посмотреть [https://raft.github.io/ официальный сайт] (с визуализацией) и посмотреть [http://thesecretlivesofdata.com/raft/ интерактивную презентацию]&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71625</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71625"/>
				<updated>2019-06-04T07:23:28Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Paxos_(computer_science)#Basic_Paxos&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Обычно используется для хранения самых-самых важных данных.&lt;br /&gt;
&lt;br /&gt;
Тут довольно много деталей опущено, так что реализовать это на практике довольно сложно&amp;lt;ref&amp;gt;https://doi.org/10.1145/1281100.1281103&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Роли ===&lt;br /&gt;
Мы хотим достичь согласованного консенсуса.&lt;br /&gt;
У нас есть несколько процессов, у каждого есть некоторое подмножество ролей:&lt;br /&gt;
* Предлагающий (proposer) — может выдвинуть предложение&lt;br /&gt;
* Принимающий (acceptor) — принимают консенсус&lt;br /&gt;
* Узнающий (learner) — тот, кто узнаёт про принятый консенсус&lt;br /&gt;
Дальше алгоритм говорит исключительно про роли, а не процессы.&lt;br /&gt;
Обычно в каждом процессе совмещаются все три роли.&lt;br /&gt;
&lt;br /&gt;
У алгоритма статическая конфигурация: в базовой версии мы не можем добавлять новые роли в процессе работы.&lt;br /&gt;
Переконфигурация — отдельная интересная инженерная задача.&lt;br /&gt;
&lt;br /&gt;
=== Лидер ===&lt;br /&gt;
Если у нас только один принимающий процесс, то всё просто, но нет защиты от отказов.&lt;br /&gt;
По этому должно быть несколько принимающих процессов.&lt;br /&gt;
Алгоритм Paxos требует, чтобы решение принималось [[Кворум|кворумом]] процессов.&lt;br /&gt;
Обычно берут кворум простого большинства и 3-5 процессов, выбирают из соображений надёжности: процесс может уйти в swap и это нестрашно (система-то асинхронная), а может полностью отказать (тогда его надо физически заменить).&lt;br /&gt;
&lt;br /&gt;
На самом деле мы не пытаемся сразу принять консенсус, а сначала [[Переформулировки консенсуса в распределённой системе#Выбор лидера|выбираем лидера]],&lt;br /&gt;
что эквивалентно консенсусу, но зато потом можно очень быстро работать, если никто не падает.&lt;br /&gt;
Лидера выбираем из предлагающих процессов (судя по статье на Хабре, а в лекции говорилось, что из принимающих).&lt;br /&gt;
&lt;br /&gt;
Лидера можно просто и быстро выбрать, если нет отказов.&lt;br /&gt;
А если есть — можно просто и быстро выбрать (предположив синхронность системы), но, возможно, будет несколько лидеров.&lt;br /&gt;
Тем не менее, Paxos всё ещё будет гарантировать согласие и в этом случае.&lt;br /&gt;
Возможно, будет работать бесконечно долго, но согласие будет.&lt;br /&gt;
&lt;br /&gt;
А на практике для получения нескольких лидеров надо, чтобы что-то пошло не так ровно в момент выборов лидера, а это очень быстрый процесс.&lt;br /&gt;
Так что на практике лидер почти всегда один и всё работает.&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
К консенсусу мы приходим за несколько голосований.&lt;br /&gt;
Каждое голосование инициирует лидер (возможно, несколько лидеров параллельно, если нам не повезло).&lt;br /&gt;
&lt;br /&gt;
У каждого голосования есть уникальный номер $k$: нам требуется, чтобы они в голосованиях были уникальны и возрастали.&lt;br /&gt;
Этого можно достичь, если номер — это пара из [[Логические часы Лампорта|логических часов]] и фиксированного уникального номера процесса.&lt;br /&gt;
Можно не гонять логические часы на вообще все сообщения, а строить их только на известных процессу номерах голосований, тоже пойдёт.&lt;br /&gt;
&lt;br /&gt;
Примерная схема: на фазе 1 лидер добивается от кворума принимающих ''обещание'', что они за него, а на фазе 2 выбирает какое-то предложение и рассылает его своим принимающим.&lt;br /&gt;
У принимающего есть две независимых компоненты состояния: кому он что-нибудь ''пообещал'' (только лидер и номер голосования) и какое предложение он ''принял'' (от какого лидера, номер голосования, какое значение).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1a (подготовка)''': лидер посылает сообщение $(1a, k)$ всем принимающим (и ждёт ответа от кворума на второй фазе). Пока никаких предложений нет.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1b (обещание)''': каждый принимающий начинает выбирать предложение с максимальным номером:&lt;br /&gt;
# Если пришло предложение больше, чем все предыдущие, то принимающий ''обещает'' лидеру не принимать предложения с меньшим номером, отвечает $(1b, k, ack, 0, 0)$.&lt;br /&gt;
Но если какое-то предложение с меньшим номером $k'$ уже было ''принято'' со значением $v'$ (это происходит на фазе 2), то отвечает $(1b, k, ack, k', v')$, чтобы лидер был в курсе.&lt;br /&gt;
# Если пришло предложение меньше, чем имеющийся максимум $k''$, ничего не делаем. Ну, можем ответить $(1b, k', nack)$ для оптимизации.&lt;br /&gt;
Если лидер видит хотя бы один nack, то он понимает, что его обогнали, и начинает фазу 1 заново, подняв своё $k$ до присланного $k'+1$ (это просто оптимизация, чтобы не тормозить с перевыбором лидера).&lt;br /&gt;
Таким образом, если у нас несколько лидеров, они будут друг другу активно мешать.&lt;br /&gt;
То есть они в какой-то момент как-то должны догадаться, что их много (как?).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2a (запрос)''': если лидеру удалось собрать кворум обещаний, то он должен попросить принимающих ''принять'' какое-то значение.&lt;br /&gt;
Если ему кто-то сказал, что уже принял значение $v_1$, $v_2$, ..., то выбираем значение с максимальным номером голосования.&lt;br /&gt;
А если никто ничего не принимал, то лидер вносит своё предложение.&lt;br /&gt;
После этого рассылает предложение принимающим, хотя бы кворуму: $(2a, k, v)$, где $v$ — выбранное лидером предложение.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2b (подтверждение''': если принимающий получает запрос $(2a, k, v)$ и он ещё не дал обещание для $k' &amp;gt; k$, то он ''принимает'' предложение $(k, v)$ и посылает сообщение $(2b, k, v)$ всем узнающим.&lt;br /&gt;
После этого во всех следующих голосованиях всем существующим лидерам принимающий будет сообщать лидеру, что он уже принял какое-то предложение.&lt;br /&gt;
А лидер будет пытаться это мнение учитывать.&lt;br /&gt;
&lt;br /&gt;
Узнающий принимает решение: если он получил одинаковое сообщение $(2b, k, v)$ от кворума принимающих, то алгоритм Paxos выбрал значение $v$.&lt;br /&gt;
&lt;br /&gt;
==== Обработка отказов ====&lt;br /&gt;
Обычно делается таймаутами(?) и рандомом(?):&lt;br /&gt;
* Если лидеру не удалось собрать консенсус за какое-то время, он может забить и попробовать ещё раз.&lt;br /&gt;
* Если какой-то узел давно не слышал от лидера, он может инициировать перевыбора&lt;br /&gt;
* Если лидер увидел второго лидера, можно выбрать, кому жить (например, тому, у кого номер голосования меньше)&lt;br /&gt;
&lt;br /&gt;
Все эти трюки на корректность не влияют(?) и в каком-то смысле вторичны по сравнению с ядром Paxos.&lt;br /&gt;
Но на практике работают хорошо, сбои-то у нас редкие.&lt;br /&gt;
&lt;br /&gt;
==== Количество сообщений ====&lt;br /&gt;
На каждый консенсус у нас задержка хотя бы в четыре сообщения: 1a, 1b, 2a, 2b.&lt;br /&gt;
&lt;br /&gt;
==== Наблюдения про корректность ====&lt;br /&gt;
Paxos гарантирует, что если было в конце было выбрано значение $v$, то никакое другое никогда больше не может быть выбрано.&lt;br /&gt;
В самом деле: если у нас получилось сообщение $(2b, k, v)$ от одного кворума принимающих и сообщение $(2b, k', v')$ от другого кворума принимающих, то эти кворумы пересекаются по принимающему $P$.&lt;br /&gt;
Не умаляя общности считаем, что $k &amp;lt; k'$.&lt;br /&gt;
&lt;br /&gt;
Тогда получаем, что $P$ сначала в голосовании $k$ принял от лидера предложение $v$, а потом в голосовании $k' &amp;gt; k$ сообщил об этом лидеру, но тот всё равно выбрал не $v$, а $v'$.&lt;br /&gt;
Значит, $v'$ было получено от какого-то принимающего с комментарием &amp;quot;я принял его в голосовании $k'' &amp;gt; k$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Модификации ==&lt;br /&gt;
Переконфигурация — отдельная задача.&lt;br /&gt;
&lt;br /&gt;
=== Multi paxos ===&lt;br /&gt;
Если нам нужно прийти к нескольким консенсусам, то можно вместо запуска нескольких копий Paxos выполнить выбор лидера и первую фазу один раз для всех копий сразу.&lt;br /&gt;
Тогда в них будут одинаковые голосования, но они всё ещё будут работать.&lt;br /&gt;
Зато сильно сокращается задержка.&lt;br /&gt;
&lt;br /&gt;
=== Fast Paxos ===&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Paxos ===&lt;br /&gt;
Можно добавить отдельную операцию &amp;quot;изменение конфигурации&amp;quot; в RSM.&lt;br /&gt;
&lt;br /&gt;
=== Cheap Paxos ===&lt;br /&gt;
Если мы хотим пережить много отказов и нам нужно много процессов, то базовый Paxos посылает сообщение всем и ждёт кворума.&lt;br /&gt;
Работает быстро, но шлёт много сообщений.&lt;br /&gt;
Можно сначала слать только какому-то конкретному элементу кворума, а остальных игнорировать.&lt;br /&gt;
И подключать остальных только если кворум долго не отвечает.&lt;br /&gt;
&lt;br /&gt;
В обычном режиме будет меньше сообщений, но при сбоях увеличивается задержка (потому что нужно обнаружить сбой и подключить лежащие в стороне процессы).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71624</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71624"/>
				<updated>2019-06-04T07:21:50Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Модификации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Paxos_(computer_science)#Basic_Paxos&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Обычно используется для хранения самых-самых важных данных.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Роли ===&lt;br /&gt;
Мы хотим достичь согласованного консенсуса.&lt;br /&gt;
У нас есть несколько процессов, у каждого есть некоторое подмножество ролей:&lt;br /&gt;
* Предлагающий (proposer) — может выдвинуть предложение&lt;br /&gt;
* Принимающий (acceptor) — принимают консенсус&lt;br /&gt;
* Узнающий (learner) — тот, кто узнаёт про принятый консенсус&lt;br /&gt;
Дальше алгоритм говорит исключительно про роли, а не процессы.&lt;br /&gt;
Обычно в каждом процессе совмещаются все три роли.&lt;br /&gt;
&lt;br /&gt;
У алгоритма статическая конфигурация: в базовой версии мы не можем добавлять новые роли в процессе работы.&lt;br /&gt;
Переконфигурация — отдельная интересная инженерная задача.&lt;br /&gt;
&lt;br /&gt;
=== Лидер ===&lt;br /&gt;
Если у нас только один принимающий процесс, то всё просто, но нет защиты от отказов.&lt;br /&gt;
По этому должно быть несколько принимающих процессов.&lt;br /&gt;
Алгоритм Paxos требует, чтобы решение принималось [[Кворум|кворумом]] процессов.&lt;br /&gt;
Обычно берут кворум простого большинства и 3-5 процессов, выбирают из соображений надёжности: процесс может уйти в swap и это нестрашно (система-то асинхронная), а может полностью отказать (тогда его надо физически заменить).&lt;br /&gt;
&lt;br /&gt;
На самом деле мы не пытаемся сразу принять консенсус, а сначала [[Переформулировки консенсуса в распределённой системе#Выбор лидера|выбираем лидера]],&lt;br /&gt;
что эквивалентно консенсусу, но зато потом можно очень быстро работать, если никто не падает.&lt;br /&gt;
Лидера выбираем из предлагающих процессов (судя по статье на Хабре, а в лекции говорилось, что из принимающих).&lt;br /&gt;
&lt;br /&gt;
Лидера можно просто и быстро выбрать, если нет отказов.&lt;br /&gt;
А если есть — можно просто и быстро выбрать (предположив синхронность системы), но, возможно, будет несколько лидеров.&lt;br /&gt;
Тем не менее, Paxos всё ещё будет гарантировать согласие и в этом случае.&lt;br /&gt;
Возможно, будет работать бесконечно долго, но согласие будет.&lt;br /&gt;
&lt;br /&gt;
А на практике для получения нескольких лидеров надо, чтобы что-то пошло не так ровно в момент выборов лидера, а это очень быстрый процесс.&lt;br /&gt;
Так что на практике лидер почти всегда один и всё работает.&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
К консенсусу мы приходим за несколько голосований.&lt;br /&gt;
Каждое голосование инициирует лидер (возможно, несколько лидеров параллельно, если нам не повезло).&lt;br /&gt;
&lt;br /&gt;
У каждого голосования есть уникальный номер $k$: нам требуется, чтобы они в голосованиях были уникальны и возрастали.&lt;br /&gt;
Этого можно достичь, если номер — это пара из [[Логические часы Лампорта|логических часов]] и фиксированного уникального номера процесса.&lt;br /&gt;
Можно не гонять логические часы на вообще все сообщения, а строить их только на известных процессу номерах голосований, тоже пойдёт.&lt;br /&gt;
&lt;br /&gt;
Примерная схема: на фазе 1 лидер добивается от кворума принимающих ''обещание'', что они за него, а на фазе 2 выбирает какое-то предложение и рассылает его своим принимающим.&lt;br /&gt;
У принимающего есть две независимых компоненты состояния: кому он что-нибудь ''пообещал'' (только лидер и номер голосования) и какое предложение он ''принял'' (от какого лидера, номер голосования, какое значение).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1a (подготовка)''': лидер посылает сообщение $(1a, k)$ всем принимающим (и ждёт ответа от кворума на второй фазе). Пока никаких предложений нет.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1b (обещание)''': каждый принимающий начинает выбирать предложение с максимальным номером:&lt;br /&gt;
# Если пришло предложение больше, чем все предыдущие, то принимающий ''обещает'' лидеру не принимать предложения с меньшим номером, отвечает $(1b, k, ack, 0, 0)$.&lt;br /&gt;
Но если какое-то предложение с меньшим номером $k'$ уже было ''принято'' со значением $v'$ (это происходит на фазе 2), то отвечает $(1b, k, ack, k', v')$, чтобы лидер был в курсе.&lt;br /&gt;
# Если пришло предложение меньше, чем имеющийся максимум $k''$, ничего не делаем. Ну, можем ответить $(1b, k', nack)$ для оптимизации.&lt;br /&gt;
Если лидер видит хотя бы один nack, то он понимает, что его обогнали, и начинает фазу 1 заново, подняв своё $k$ до присланного $k'+1$ (это просто оптимизация, чтобы не тормозить с перевыбором лидера).&lt;br /&gt;
Таким образом, если у нас несколько лидеров, они будут друг другу активно мешать.&lt;br /&gt;
То есть они в какой-то момент как-то должны догадаться, что их много (как?).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2a (запрос)''': если лидеру удалось собрать кворум обещаний, то он должен попросить принимающих ''принять'' какое-то значение.&lt;br /&gt;
Если ему кто-то сказал, что уже принял значение $v_1$, $v_2$, ..., то выбираем значение с максимальным номером голосования.&lt;br /&gt;
А если никто ничего не принимал, то лидер вносит своё предложение.&lt;br /&gt;
После этого рассылает предложение принимающим, хотя бы кворуму: $(2a, k, v)$, где $v$ — выбранное лидером предложение.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2b (подтверждение''': если принимающий получает запрос $(2a, k, v)$ и он ещё не дал обещание для $k' &amp;gt; k$, то он ''принимает'' предложение $(k, v)$ и посылает сообщение $(2b, k, v)$ всем узнающим.&lt;br /&gt;
После этого во всех следующих голосованиях всем существующим лидерам принимающий будет сообщать лидеру, что он уже принял какое-то предложение.&lt;br /&gt;
А лидер будет пытаться это мнение учитывать.&lt;br /&gt;
&lt;br /&gt;
Узнающий принимает решение: если он получил одинаковое сообщение $(2b, k, v)$ от кворума принимающих, то алгоритм Paxos выбрал значение $v$.&lt;br /&gt;
&lt;br /&gt;
==== Обработка отказов ====&lt;br /&gt;
Обычно делается таймаутами(?) и рандомом(?):&lt;br /&gt;
* Если лидеру не удалось собрать консенсус за какое-то время, он может забить и попробовать ещё раз.&lt;br /&gt;
* Если какой-то узел давно не слышал от лидера, он может инициировать перевыбора&lt;br /&gt;
* Если лидер увидел второго лидера, можно выбрать, кому жить (например, тому, у кого номер голосования меньше)&lt;br /&gt;
&lt;br /&gt;
Все эти трюки на корректность не влияют(?) и в каком-то смысле вторичны по сравнению с ядром Paxos.&lt;br /&gt;
Но на практике работают хорошо, сбои-то у нас редкие.&lt;br /&gt;
&lt;br /&gt;
==== Количество сообщений ====&lt;br /&gt;
На каждый консенсус у нас задержка хотя бы в четыре сообщения: 1a, 1b, 2a, 2b.&lt;br /&gt;
&lt;br /&gt;
==== Наблюдения про корректность ====&lt;br /&gt;
Paxos гарантирует, что если было в конце было выбрано значение $v$, то никакое другое никогда больше не может быть выбрано.&lt;br /&gt;
В самом деле: если у нас получилось сообщение $(2b, k, v)$ от одного кворума принимающих и сообщение $(2b, k', v')$ от другого кворума принимающих, то эти кворумы пересекаются по принимающему $P$.&lt;br /&gt;
Не умаляя общности считаем, что $k &amp;lt; k'$.&lt;br /&gt;
&lt;br /&gt;
Тогда получаем, что $P$ сначала в голосовании $k$ принял от лидера предложение $v$, а потом в голосовании $k' &amp;gt; k$ сообщил об этом лидеру, но тот всё равно выбрал не $v$, а $v'$.&lt;br /&gt;
Значит, $v'$ было получено от какого-то принимающего с комментарием &amp;quot;я принял его в голосовании $k'' &amp;gt; k$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Модификации ==&lt;br /&gt;
Переконфигурация — отдельная задача.&lt;br /&gt;
&lt;br /&gt;
=== Multi paxos ===&lt;br /&gt;
Если нам нужно прийти к нескольким консенсусам, то можно вместо запуска нескольких копий Paxos выполнить выбор лидера и первую фазу один раз для всех копий сразу.&lt;br /&gt;
Тогда в них будут одинаковые голосования, но они всё ещё будут работать.&lt;br /&gt;
Зато сильно сокращается задержка.&lt;br /&gt;
&lt;br /&gt;
=== Fast Paxos ===&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Paxos ===&lt;br /&gt;
Можно добавить отдельную операцию &amp;quot;изменение конфигурации&amp;quot; в RSM.&lt;br /&gt;
&lt;br /&gt;
=== Cheap Paxos ===&lt;br /&gt;
Если мы хотим пережить много отказов и нам нужно много процессов, то базовый Paxos посылает сообщение всем и ждёт кворума.&lt;br /&gt;
Работает быстро, но шлёт много сообщений.&lt;br /&gt;
Можно сначала слать только какому-то конкретному элементу кворума, а остальных игнорировать.&lt;br /&gt;
И подключать остальных только если кворум долго не отвечает.&lt;br /&gt;
&lt;br /&gt;
В обычном режиме будет меньше сообщений, но при сбоях увеличивается задержка (потому что нужно обнаружить сбой и подключить лежащие в стороне процессы).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71623</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71623"/>
				<updated>2019-06-04T07:20:08Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Paxos_(computer_science)#Basic_Paxos&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Обычно используется для хранения самых-самых важных данных.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Роли ===&lt;br /&gt;
Мы хотим достичь согласованного консенсуса.&lt;br /&gt;
У нас есть несколько процессов, у каждого есть некоторое подмножество ролей:&lt;br /&gt;
* Предлагающий (proposer) — может выдвинуть предложение&lt;br /&gt;
* Принимающий (acceptor) — принимают консенсус&lt;br /&gt;
* Узнающий (learner) — тот, кто узнаёт про принятый консенсус&lt;br /&gt;
Дальше алгоритм говорит исключительно про роли, а не процессы.&lt;br /&gt;
Обычно в каждом процессе совмещаются все три роли.&lt;br /&gt;
&lt;br /&gt;
У алгоритма статическая конфигурация: в базовой версии мы не можем добавлять новые роли в процессе работы.&lt;br /&gt;
Переконфигурация — отдельная интересная инженерная задача.&lt;br /&gt;
&lt;br /&gt;
=== Лидер ===&lt;br /&gt;
Если у нас только один принимающий процесс, то всё просто, но нет защиты от отказов.&lt;br /&gt;
По этому должно быть несколько принимающих процессов.&lt;br /&gt;
Алгоритм Paxos требует, чтобы решение принималось [[Кворум|кворумом]] процессов.&lt;br /&gt;
Обычно берут кворум простого большинства и 3-5 процессов, выбирают из соображений надёжности: процесс может уйти в swap и это нестрашно (система-то асинхронная), а может полностью отказать (тогда его надо физически заменить).&lt;br /&gt;
&lt;br /&gt;
На самом деле мы не пытаемся сразу принять консенсус, а сначала [[Переформулировки консенсуса в распределённой системе#Выбор лидера|выбираем лидера]],&lt;br /&gt;
что эквивалентно консенсусу, но зато потом можно очень быстро работать, если никто не падает.&lt;br /&gt;
Лидера выбираем из предлагающих процессов (судя по статье на Хабре, а в лекции говорилось, что из принимающих).&lt;br /&gt;
&lt;br /&gt;
Лидера можно просто и быстро выбрать, если нет отказов.&lt;br /&gt;
А если есть — можно просто и быстро выбрать (предположив синхронность системы), но, возможно, будет несколько лидеров.&lt;br /&gt;
Тем не менее, Paxos всё ещё будет гарантировать согласие и в этом случае.&lt;br /&gt;
Возможно, будет работать бесконечно долго, но согласие будет.&lt;br /&gt;
&lt;br /&gt;
А на практике для получения нескольких лидеров надо, чтобы что-то пошло не так ровно в момент выборов лидера, а это очень быстрый процесс.&lt;br /&gt;
Так что на практике лидер почти всегда один и всё работает.&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
К консенсусу мы приходим за несколько голосований.&lt;br /&gt;
Каждое голосование инициирует лидер (возможно, несколько лидеров параллельно, если нам не повезло).&lt;br /&gt;
&lt;br /&gt;
У каждого голосования есть уникальный номер $k$: нам требуется, чтобы они в голосованиях были уникальны и возрастали.&lt;br /&gt;
Этого можно достичь, если номер — это пара из [[Логические часы Лампорта|логических часов]] и фиксированного уникального номера процесса.&lt;br /&gt;
Можно не гонять логические часы на вообще все сообщения, а строить их только на известных процессу номерах голосований, тоже пойдёт.&lt;br /&gt;
&lt;br /&gt;
Примерная схема: на фазе 1 лидер добивается от кворума принимающих ''обещание'', что они за него, а на фазе 2 выбирает какое-то предложение и рассылает его своим принимающим.&lt;br /&gt;
У принимающего есть две независимых компоненты состояния: кому он что-нибудь ''пообещал'' (только лидер и номер голосования) и какое предложение он ''принял'' (от какого лидера, номер голосования, какое значение).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1a (подготовка)''': лидер посылает сообщение $(1a, k)$ всем принимающим (и ждёт ответа от кворума на второй фазе). Пока никаких предложений нет.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1b (обещание)''': каждый принимающий начинает выбирать предложение с максимальным номером:&lt;br /&gt;
# Если пришло предложение больше, чем все предыдущие, то принимающий ''обещает'' лидеру не принимать предложения с меньшим номером, отвечает $(1b, k, ack, 0, 0)$.&lt;br /&gt;
Но если какое-то предложение с меньшим номером $k'$ уже было ''принято'' со значением $v'$ (это происходит на фазе 2), то отвечает $(1b, k, ack, k', v')$, чтобы лидер был в курсе.&lt;br /&gt;
# Если пришло предложение меньше, чем имеющийся максимум $k''$, ничего не делаем. Ну, можем ответить $(1b, k', nack)$ для оптимизации.&lt;br /&gt;
Если лидер видит хотя бы один nack, то он понимает, что его обогнали, и начинает фазу 1 заново, подняв своё $k$ до присланного $k'+1$ (это просто оптимизация, чтобы не тормозить с перевыбором лидера).&lt;br /&gt;
Таким образом, если у нас несколько лидеров, они будут друг другу активно мешать.&lt;br /&gt;
То есть они в какой-то момент как-то должны догадаться, что их много (как?).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2a (запрос)''': если лидеру удалось собрать кворум обещаний, то он должен попросить принимающих ''принять'' какое-то значение.&lt;br /&gt;
Если ему кто-то сказал, что уже принял значение $v_1$, $v_2$, ..., то выбираем значение с максимальным номером голосования.&lt;br /&gt;
А если никто ничего не принимал, то лидер вносит своё предложение.&lt;br /&gt;
После этого рассылает предложение принимающим, хотя бы кворуму: $(2a, k, v)$, где $v$ — выбранное лидером предложение.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2b (подтверждение''': если принимающий получает запрос $(2a, k, v)$ и он ещё не дал обещание для $k' &amp;gt; k$, то он ''принимает'' предложение $(k, v)$ и посылает сообщение $(2b, k, v)$ всем узнающим.&lt;br /&gt;
После этого во всех следующих голосованиях всем существующим лидерам принимающий будет сообщать лидеру, что он уже принял какое-то предложение.&lt;br /&gt;
А лидер будет пытаться это мнение учитывать.&lt;br /&gt;
&lt;br /&gt;
Узнающий принимает решение: если он получил одинаковое сообщение $(2b, k, v)$ от кворума принимающих, то алгоритм Paxos выбрал значение $v$.&lt;br /&gt;
&lt;br /&gt;
==== Обработка отказов ====&lt;br /&gt;
Обычно делается таймаутами(?) и рандомом(?):&lt;br /&gt;
* Если лидеру не удалось собрать консенсус за какое-то время, он может забить и попробовать ещё раз.&lt;br /&gt;
* Если какой-то узел давно не слышал от лидера, он может инициировать перевыбора&lt;br /&gt;
* Если лидер увидел второго лидера, можно выбрать, кому жить (например, тому, у кого номер голосования меньше)&lt;br /&gt;
&lt;br /&gt;
Все эти трюки на корректность не влияют(?) и в каком-то смысле вторичны по сравнению с ядром Paxos.&lt;br /&gt;
Но на практике работают хорошо, сбои-то у нас редкие.&lt;br /&gt;
&lt;br /&gt;
==== Количество сообщений ====&lt;br /&gt;
На каждый консенсус у нас задержка хотя бы в четыре сообщения: 1a, 1b, 2a, 2b.&lt;br /&gt;
&lt;br /&gt;
==== Наблюдения про корректность ====&lt;br /&gt;
Paxos гарантирует, что если было в конце было выбрано значение $v$, то никакое другое никогда больше не может быть выбрано.&lt;br /&gt;
В самом деле: если у нас получилось сообщение $(2b, k, v)$ от одного кворума принимающих и сообщение $(2b, k', v')$ от другого кворума принимающих, то эти кворумы пересекаются по принимающему $P$.&lt;br /&gt;
Не умаляя общности считаем, что $k &amp;lt; k'$.&lt;br /&gt;
&lt;br /&gt;
Тогда получаем, что $P$ сначала в голосовании $k$ принял от лидера предложение $v$, а потом в голосовании $k' &amp;gt; k$ сообщил об этом лидеру, но тот всё равно выбрал не $v$, а $v'$.&lt;br /&gt;
Значит, $v'$ было получено от какого-то принимающего с комментарием &amp;quot;я принял его в голосовании $k'' &amp;gt; k$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Модификации ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71622</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71622"/>
				<updated>2019-06-04T07:16:53Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Paxos_(computer_science)#Basic_Paxos&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Обычно используется для хранения самых-самых важных данных.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Роли ===&lt;br /&gt;
Мы хотим достичь согласованного консенсуса.&lt;br /&gt;
У нас есть несколько процессов, у каждого есть некоторое подмножество ролей:&lt;br /&gt;
* Предлагающий (proposer) — может выдвинуть предложение&lt;br /&gt;
* Принимающий (acceptor) — принимают консенсус&lt;br /&gt;
* Узнающий (learner) — тот, кто узнаёт про принятый консенсус&lt;br /&gt;
Дальше алгоритм говорит исключительно про роли, а не процессы.&lt;br /&gt;
Обычно в каждом процессе совмещаются все три роли.&lt;br /&gt;
&lt;br /&gt;
У алгоритма статическая конфигурация: в базовой версии мы не можем добавлять новые роли в процессе работы.&lt;br /&gt;
Переконфигурация — отдельная интересная инженерная задача.&lt;br /&gt;
&lt;br /&gt;
=== Лидер ===&lt;br /&gt;
Если у нас только один принимающий процесс, то всё просто, но нет защиты от отказов.&lt;br /&gt;
По этому должно быть несколько принимающих процессов.&lt;br /&gt;
Алгоритм Paxos требует, чтобы решение принималось [[Кворум|кворумом]] процессов.&lt;br /&gt;
Обычно берут кворум простого большинства и 3-5 процессов, выбирают из соображений надёжности: процесс может уйти в swap и это нестрашно (система-то асинхронная), а может полностью отказать (тогда его надо физически заменить).&lt;br /&gt;
&lt;br /&gt;
На самом деле мы не пытаемся сразу принять консенсус, а сначала [[Переформулировки консенсуса в распределённой системе#Выбор лидера|выбираем лидера]],&lt;br /&gt;
что эквивалентно консенсусу, но зато потом можно очень быстро работать, если никто не падает.&lt;br /&gt;
Лидера выбираем из предлагающих процессов (судя по статье на Хабре, а в лекции говорилось, что из принимающих).&lt;br /&gt;
&lt;br /&gt;
Лидера можно просто и быстро выбрать, если нет отказов.&lt;br /&gt;
А если есть — можно просто и быстро выбрать (предположив синхронность системы), но, возможно, будет несколько лидеров.&lt;br /&gt;
Тем не менее, Paxos всё ещё будет гарантировать согласие и в этом случае.&lt;br /&gt;
Возможно, будет работать бесконечно долго, но согласие будет.&lt;br /&gt;
&lt;br /&gt;
А на практике для получения нескольких лидеров надо, чтобы что-то пошло не так ровно в момент выборов лидера, а это очень быстрый процесс.&lt;br /&gt;
Так что на практике лидер почти всегда один и всё работает.&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
К консенсусу мы приходим за несколько голосований.&lt;br /&gt;
Каждое голосование инициирует лидер (возможно, несколько лидеров параллельно, если нам не повезло).&lt;br /&gt;
&lt;br /&gt;
У каждого голосования есть уникальный номер $k$: нам требуется, чтобы они в голосованиях были уникальны и возрастали.&lt;br /&gt;
Этого можно достичь, если номер — это пара из [[Логические часы Лампорта|логических часов]] и фиксированного уникального номера процесса.&lt;br /&gt;
Можно не гонять логические часы на вообще все сообщения, а строить их только на известных процессу номерах голосований, тоже пойдёт.&lt;br /&gt;
&lt;br /&gt;
Примерная схема: на фазе 1 лидер добивается от кворума принимающих ''обещание'', что они за него, а на фазе 2 выбирает какое-то предложение и рассылает его своим принимающим.&lt;br /&gt;
У принимающего есть две независимых компоненты состояния: кому он что-нибудь ''пообещал'' (только лидер и номер голосования) и какое предложение он ''принял'' (от какого лидера, номер голосования, какое значение).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1a (подготовка)''': лидер посылает сообщение $(1a, k)$ кворуму принимающих (или вообще всем, а ждёт ответа от кворума?). Пока никаких предложений нет.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 1b (обещание)''': каждый принимающий начинает выбирать предложение с максимальным номером:&lt;br /&gt;
# Если пришло предложение больше, чем все предыдущие, то принимающий ''обещает'' лидеру не принимать предложения с меньшим номером, отвечает $(1b, k, ack, 0, 0)$.&lt;br /&gt;
Но если какое-то предложение с меньшим номером $k'$ уже было ''принято'' со значением $v'$ (это происходит на фазе 2), то отвечает $(1b, k, ack, k', v')$, чтобы лидер был в курсе.&lt;br /&gt;
# Если пришло предложение меньше, чем имеющийся максимум $k''$, ничего не делаем. Ну, можем ответить $(1b, k', nack)$ для оптимизации.&lt;br /&gt;
Если лидер видит хотя бы один nack, то он понимает, что его обогнали, и начинает фазу 1 заново, подняв своё $k$ до присланного $k'+1$ (это просто оптимизация, чтобы не тормозить с перевыбором лидера).&lt;br /&gt;
Таким образом, если у нас несколько лидеров, они будут друг другу активно мешать.&lt;br /&gt;
То есть они в какой-то момент как-то должны догадаться, что их много (как?).&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2a (запрос)''': если лидеру удалось собрать кворум обещаний, то он должен попросить принимающих ''принять'' какое-то значение.&lt;br /&gt;
Если ему кто-то сказал, что уже принял значение $v_1$, $v_2$, ..., то выбираем значение с максимальным номером голосования.&lt;br /&gt;
А если никто ничего не принимал, то лидер вносит своё предложение.&lt;br /&gt;
После этого рассылает предложение принимающим, хотя бы кворуму: $(2a, k, v)$, где $v$ — выбранное лидером предложение.&lt;br /&gt;
&lt;br /&gt;
'''Фаза 2b (подтверждение''': если принимающий получает запрос $(2a, k, v)$ и он ещё не дал обещание для $k' &amp;gt; k$, то он ''принимает'' предложение $(k, v)$ и посылает сообщение $(2b, k, v)$ всем узнающим.&lt;br /&gt;
После этого во всех следующих голосованиях всем существующим лидерам принимающий будет сообщать лидеру, что он уже принял какое-то предложение.&lt;br /&gt;
А лидер будет пытаться это мнение учитывать.&lt;br /&gt;
&lt;br /&gt;
Узнающий принимает решение: если он получил одинаковое сообщение $(2b, k, v)$ от кворума принимающих, то алгоритм Paxos выбрал значение $v$.&lt;br /&gt;
&lt;br /&gt;
==== Обработка отказов ====&lt;br /&gt;
Обычно делается таймаутами(?) и рандомом(?):&lt;br /&gt;
* Если лидеру не удалось собрать консенсус за какое-то время, он может забить и попробовать ещё раз.&lt;br /&gt;
* Если какой-то узел давно не слышал от лидера, он может инициировать перевыбора&lt;br /&gt;
* Если лидер увидел второго лидера, можно выбрать, кому жить (например, тому, у кого номер голосования меньше)&lt;br /&gt;
&lt;br /&gt;
Все эти трюки на корректность не влияют(?) и в каком-то смысле вторичны по сравнению с ядром Paxos.&lt;br /&gt;
Но на практике работают хорошо, сбои-то у нас редкие.&lt;br /&gt;
&lt;br /&gt;
==== Количество сообщений ====&lt;br /&gt;
На каждый консенсус у нас задержка хотя бы в четыре сообщения: 1a, 1b, 2a, 2b.&lt;br /&gt;
&lt;br /&gt;
==== Наблюдения про корректность ====&lt;br /&gt;
Paxos гарантирует, что если было в конце было выбрано значение $v$, то никакое другое никогда больше не может быть выбрано.&lt;br /&gt;
В самом деле: если у нас получилось сообщение $(2b, k, v)$ от одного кворума принимающих и сообщение $(2b, k', v')$ от другого кворума принимающих, то эти кворумы пересекаются по принимающему $P$.&lt;br /&gt;
Не умаляя общности считаем, что $k &amp;lt; k'$.&lt;br /&gt;
&lt;br /&gt;
Тогда получаем, что $P$ сначала в голосовании $k$ принял от лидера предложение $v$, а потом в голосовании $k' &amp;gt; k$ сообщил об этом лидеру, но тот всё равно выбрал не $v$, а $v'$.&lt;br /&gt;
Значит, $v'$ было получено от какого-то принимающего с комментарием &amp;quot;я принял его в голосовании $k'' &amp;gt; k$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Модификации ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71621</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71621"/>
				<updated>2019-06-04T07:04:05Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Paxos_(computer_science)#Basic_Paxos&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Обычно используется для хранения самых-самых важных данных.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
== Модификации ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71620</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71620"/>
				<updated>2019-06-04T06:19:10Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Обычно используется для хранения самых-самых важных данных.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
== Модификации ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71619</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71619"/>
				<updated>2019-06-04T06:18:16Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Обычно используется для хранения самых-самых важных данных или [[Переформулировки консенсуса в распределённой системе#Выбор лидера|выбора лидера]].&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
== Модификации ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71618</id>
		<title>Replicated State Machine</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71618"/>
				<updated>2019-06-04T06:17:04Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Replicated State Machine''' — система, которая хранит некий автомат (state machine) распределённо, а пользователи могут применять к этому автомату операции.&lt;br /&gt;
После этого RSM обязана эту операцию либо атомарно применить, либо откатить, и сообщить об этом пользователю.&lt;br /&gt;
Подтверждённые пользователю транзакции теряться не должны.&lt;br /&gt;
&lt;br /&gt;
Это может быть полезно, когда у нас есть очень важные данные, которые надо:&lt;br /&gt;
# Защитить от сбоев любого конкретного узла (т.е. надо хранить на нескольких узлах и нельзя иметь центрального координатора)&lt;br /&gt;
# Быстро обновлять (т.е. нельзя просто записывать на диск каждый раз)&lt;br /&gt;
&lt;br /&gt;
Если операции, применяемые к состоянию, детерминированы, то можно не клонировать состояние между машинами, а просто применять операции повторно на разных узлах.&lt;br /&gt;
Но операции обычно не коммутируют, поэтому всем узлам надо приходить к консенсусу: какие операции в каком порядке применять.&lt;br /&gt;
&lt;br /&gt;
Теоретически эта задача считается эквивалентной задаче консенсуса, поэтому действуют ограничения [[Теорема Фишера-Линча-Патерсона (FLP)|FLP]].&lt;br /&gt;
Нам обязательно нужна защита от отказов (иначе непонятно, зачем клонировать автомат),&lt;br /&gt;
рандом из [[Алгоритм Бен-Ора|алгоритма Бен-Ора]] &amp;quot;не сильно спасает&amp;quot; (как говорилось на лекции; вероятно, тут подразумевается его тормознутость),&lt;br /&gt;
а надеяться на синхронность системы на практике не хочется (&amp;quot;вдруг сообщение придёт не скоро? или в swap кто-то ушёл&amp;quot; с лекции).&lt;br /&gt;
По этому поводу мы обычно жертвуем завершением за конечное время: алгоритм [[Paxos]].&lt;br /&gt;
&lt;br /&gt;
Однако на практике могут возникать дополнительные сложности с тем, что узлы у нас не падают навсегда, а временно уходят и поднимаются обратно (т.е. [[Иерархия ошибок в распределённых системах|с точки зрения теории]] у нас, строго говоря, ненадёжная доставка сообщений), а нам надо консенсус запускать несколько раз и ещё как-то доносить старые решения до вернувшихся узлов (чтобы на них тоже получилось корректное состояние).&lt;br /&gt;
В алгоритме [[Raft]] это отдельно разбирается.&lt;br /&gt;
&lt;br /&gt;
По факту применяются и [[Paxos]], и [[Raft]] и все живут.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71617</id>
		<title>Paxos</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Paxos&amp;diff=71617"/>
				<updated>2019-06-04T06:13:18Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: Новая страница: «Категория:Параллельное программирование '''Paxos''' — алгоритм Консенсус в распределённ…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Paxos''' — алгоритм [[Консенсус в распределённой системе|консенсуса в распределённой системе]], который детерминированно работает в асинхронной системе с отказами узлов, гарантирует корректный консенсус, но не гарантирует, что тот при наличии отказов будет достигнут на конечное время.&lt;br /&gt;
&lt;br /&gt;
Это первый придуманный практический алгоритм консенсуса такого вида.&lt;br /&gt;
Он быстро работает и не приходит к согласию в очень редких случаях, на практике такого не случается.&lt;br /&gt;
&lt;br /&gt;
Описан много где разными словами&amp;lt;ref&amp;gt;https://habr.com/ru/post/346180/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://lamport.azurewebsites.net/pubs/paxos-simple.pdf&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/222825/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
== Модификации ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71616</id>
		<title>Replicated State Machine</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71616"/>
				<updated>2019-06-04T06:08:03Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
'''Replicated State Machine''' — система, которая хранит некий автомат (state machine) распределённо, а пользователи могут применять к этому автомату операции.&lt;br /&gt;
После этого RSM обязана эту операцию либо атомарно применить, либо откатить, и сообщить об этом пользователю.&lt;br /&gt;
Подтверждённые пользователю транзакции теряться не должны.&lt;br /&gt;
&lt;br /&gt;
Это может быть полезно, когда у нас есть очень важные данные, которые надо:&lt;br /&gt;
# Защитить от сбоев любого конкретного узла (т.е. надо хранить на нескольких узлах и нельзя иметь центрального координатора)&lt;br /&gt;
# Быстро обновлять (т.е. нельзя просто записывать на диск каждый раз)&lt;br /&gt;
&lt;br /&gt;
Если операции, применяемые к состоянию, детерминированы, то можно не клонировать состояние между машинами, а просто применять операции повторно на разных узлах.&lt;br /&gt;
Но операции обычно не коммутируют, поэтому всем узлам надо приходить к консенсусу: какие операции в каком порядке применять.&lt;br /&gt;
&lt;br /&gt;
Теоретически эта задача считается эквивалентной задаче консенсуса, поэтому действуют ограничения [[Теорема Фишера-Линча-Патерсона (FLP)|FLP]].&lt;br /&gt;
Нам обязательно нужна защита от отказов (иначе непонятно, зачем клонировать автомат),&lt;br /&gt;
рандом из [[Алгоритм Бен-Ора|алгоритма Бен-Ора]] &amp;quot;не сильно спасает&amp;quot; (как говорилось на лекции; вероятно, тут подразумевается его тормознутость),&lt;br /&gt;
а надеяться на синхронность системы на практике не хочется (&amp;quot;вдруг сообщение придёт не скоро?&amp;quot; с лекции).&lt;br /&gt;
По этому поводу мы обычно жертвуем завершением за конечное время: алгоритм [[Paxos]].&lt;br /&gt;
&lt;br /&gt;
Однако на практике могут возникать дополнительные сложности с тем, что узлы у нас не падают навсегда, а временно уходят и поднимаются обратно (т.е. [[Иерархия ошибок в распределённых системах|с точки зрения теории]] у нас, строго говоря, ненадёжная доставка сообщений), а нам надо консенсус запускать несколько раз и ещё как-то доносить старые решения до вернувшихся узлов (чтобы на них тоже получилось корректное состояние).&lt;br /&gt;
В алгоритме [[Raft]] это отдельно разбирается.&lt;br /&gt;
&lt;br /&gt;
По факту применяются и [[Paxos]], и [[Raft]] и все живут.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71615</id>
		<title>Replicated State Machine</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71615"/>
				<updated>2019-06-04T06:07:51Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Replicated State Machine''' — система, которая хранит некий автомат (state machine) распределённо, а пользователи могут применять к этому автомату операции.&lt;br /&gt;
После этого RSM обязана эту операцию либо атомарно применить, либо откатить, и сообщить об этом пользователю.&lt;br /&gt;
Подтверждённые пользователю транзакции теряться не должны.&lt;br /&gt;
&lt;br /&gt;
Это может быть полезно, когда у нас есть очень важные данные, которые надо:&lt;br /&gt;
# Защитить от сбоев любого конкретного узла (т.е. надо хранить на нескольких узлах и нельзя иметь центрального координатора)&lt;br /&gt;
# Быстро обновлять (т.е. нельзя просто записывать на диск каждый раз)&lt;br /&gt;
&lt;br /&gt;
Если операции, применяемые к состоянию, детерминированы, то можно не клонировать состояние между машинами, а просто применять операции повторно на разных узлах.&lt;br /&gt;
Но операции обычно не коммутируют, поэтому всем узлам надо приходить к консенсусу: какие операции в каком порядке применять.&lt;br /&gt;
&lt;br /&gt;
Теоретически эта задача считается эквивалентной задаче консенсуса, поэтому действуют ограничения [[Теорема Фишера-Линча-Патерсона (FLP)|FLP]].&lt;br /&gt;
Нам обязательно нужна защита от отказов (иначе непонятно, зачем клонировать автомат),&lt;br /&gt;
рандом из [[Алгоритм Бен-Ора|алгоритма Бен-Ора]] &amp;quot;не сильно спасает&amp;quot; (как говорилось на лекции; вероятно, тут подразумевается его тормознутость),&lt;br /&gt;
а надеяться на синхронность системы на практике не хочется (&amp;quot;вдруг сообщение придёт не скоро?&amp;quot; с лекции).&lt;br /&gt;
По этому поводу мы обычно жертвуем завершением за конечное время: алгоритм [[Paxos]].&lt;br /&gt;
&lt;br /&gt;
Однако на практике могут возникать дополнительные сложности с тем, что узлы у нас не падают навсегда, а временно уходят и поднимаются обратно (т.е. [[Иерархия ошибок в распределённых системах|с точки зрения теории]] у нас, строго говоря, ненадёжная доставка сообщений), а нам надо консенсус запускать несколько раз и ещё как-то доносить старые решения до вернувшихся узлов (чтобы на них тоже получилось корректное состояние).&lt;br /&gt;
В алгоритме [[Raft]] это отдельно разбирается.&lt;br /&gt;
&lt;br /&gt;
По факту применяются и [[Paxos]], и [[Raft]] и все живут.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71614</id>
		<title>Параллельное программирование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71614"/>
				<updated>2019-06-04T06:06:16Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* 30 билет. Raft. Алгоритм, его свойства. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
=Программирование параллельных и распределенных систем=&lt;br /&gt;
*[[Базовые определения и формализм]]&lt;br /&gt;
*[[Алгоритмы взаимного исключения]]&lt;br /&gt;
*[[Стек Трайбера]]&lt;br /&gt;
*[[Формализм распределённых систем]]&lt;br /&gt;
&lt;br /&gt;
==6 семестр==&lt;br /&gt;
===Введение. Масштабируемость распределенных и параллельных систем, закон Амдала. Отличия распределенных систем от систем с разделяемой памятью===&lt;br /&gt;
*[[Параллельное программирование: Распределенные вычислительные системы|Распределенные системы]]&lt;br /&gt;
*[[Параллельное программирование: Масштабируемость параллельных и распределенных систем|Масштабируемость параллельных и распределенных систем]]&lt;br /&gt;
*[[Параллельное программирование: Закон Амдала| Закон Амдала]]&lt;br /&gt;
&lt;br /&gt;
===1-2 билеты. Логические часы Лампорта и векторные часы, их свойства===&lt;br /&gt;
*[[Параллельное программирование: Частичный порядок| Частичный порядок]]&lt;br /&gt;
*[[Параллельное программирование: Логические часы Лампорта| Логические часы Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Векторные часы| Векторные часы]]&lt;br /&gt;
&lt;br /&gt;
===3-4 билеты. Часы с прямой зависимостью (и их свойства) и матричные часы===&lt;br /&gt;
*[[Параллельное программирование: Часы с прямой зависимостью|Часы с прямой зависимостью]]&lt;br /&gt;
*[[Параллельное программирование: Матричные часы|Матричные часы]] (билет весной 2019 года убран)&lt;br /&gt;
&lt;br /&gt;
===5-7 билеты. Взаимное исключение в распределенной системе. Централизованный, алгоритм Лампорта, алгоритм Рикарта и Агравалы===&lt;br /&gt;
*[[Параллельное программирование: Централизованный алгоритм взаимного исключения|Централизованный алгоритм]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Лампорта взаимного исключения|Алгоритм Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Рикарта-Агравалы|Алгоритм Рикарта-Агравалы]]&lt;br /&gt;
&lt;br /&gt;
===8-10 билеты. Взаимное исключение в распределенной системе. Алгоритм обедающих философов, на основе токена, на основе кворума (простое большинство, рушащиеся стены)===&lt;br /&gt;
&lt;br /&gt;
*[[Задача обедающих философов]]&lt;br /&gt;
*[[Кворум]]&lt;br /&gt;
*[[Кворум простого большинства]]&lt;br /&gt;
*[[Кворум рушащейся стенки]]&lt;br /&gt;
&lt;br /&gt;
===11-12 билеты. Согласованное глобальное состояние (согласованный срез). Алгоритм Чанди-Лампорта. Запоминание сообщений на стороне отправителя и получателя===&lt;br /&gt;
&lt;br /&gt;
*[[Срез, согласованный срез]]&lt;br /&gt;
*[[Алгоритм Чанди-Лампорта]]&lt;br /&gt;
&lt;br /&gt;
===13-14 билеты. Глобальные свойства. Стабильные и нестабильные предикаты. Слабый конъюнктивный предикат. Централизованный и распределенный алгоритмы===&lt;br /&gt;
&lt;br /&gt;
*[[Глобальные свойства системы]]&lt;br /&gt;
*[[Слабый конъюнктивный предикат (WCP)]]&lt;br /&gt;
*[[Централизованный алгоритм для WCP]]&lt;br /&gt;
*[[Распределенный алгоритм для WCP]]&lt;br /&gt;
&lt;br /&gt;
===15 билет. Диффундирующие вычисления. Останов. Алгоритм Дейкстры и Шолтена===&lt;br /&gt;
* [[Диффундирующие вычисления]]&lt;br /&gt;
* [[Алгоритм Дейкстры и Шолтена]]&lt;br /&gt;
&lt;br /&gt;
===16 билет. Локально-стабильные предикаты, согласованные интервалы, барьерная синхронизация (3 алгоритма). Применение для определения взаимной блокировки===&lt;br /&gt;
&lt;br /&gt;
*[[Локально стабильный предикат]]&lt;br /&gt;
*[[Согласованный интервал]]&lt;br /&gt;
*[[Барьерная синхронизация (3 алгоритма)]]&lt;br /&gt;
*[[Определение взаимной блокировки]]&lt;br /&gt;
&lt;br /&gt;
===17-19 билеты. Упорядочивание сообщений. Определения, иерархия порядков. Алгоритм для FIFO. Алгоритм для причинно-согласованного порядка. Алгоритм для синхронного порядка ===&lt;br /&gt;
* [[Иерархия порядков сообщений]]&lt;br /&gt;
* [[Алгоритм для FIFO порядка]]&lt;br /&gt;
* [[Алгоритм для причинно-согласованного порядка]]&lt;br /&gt;
* [[Алгоритм для синхронного порядка]]&lt;br /&gt;
&lt;br /&gt;
===20-21 билеты. Общий порядок (total order). Алгоритмы Лампорта и Скина===&lt;br /&gt;
*[[Общий порядок сообщений]]&lt;br /&gt;
*[[Алгоритм Лампорта]]&lt;br /&gt;
*[[Алгоритм Скина]]&lt;br /&gt;
&lt;br /&gt;
===22 билет. Иерархия ошибок в распределенных системах. Отказ узла в асинхронной системе - невозможность консенсуса (доказательство Фишера-Линча-Патерсона)===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Теорема Фишера-Линча-Патерсона (FLP)]]&lt;br /&gt;
&lt;br /&gt;
===23 билет. Консенсус в распределенных системах. Применение консенсуса: выбор лидера, terminating reliable broadcast===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Переформулировки консенсуса в распределённой системе]]&lt;br /&gt;
&lt;br /&gt;
===24 билет. Синхронные системы. Алгоритм для консенсуса в случае отказа заданного числа узлов===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Консенсус в синхронных системах]]&lt;br /&gt;
&lt;br /&gt;
===25 билет. Синхронные системы. Проблема византийских генералов. Алгоритм для N &amp;gt;= 4, f = 1. Объяснить идею обобщения для f &amp;gt; 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Алгоритм Лампорта-Шостака-Пиза]] для решения проблемы&lt;br /&gt;
&lt;br /&gt;
===26 билет. Синхронные системы. Проблема византийских генералов. Невозможность решения при N = 3, f = 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Невозможность византийского консенсуса]] при N=3, f=1.&lt;br /&gt;
&lt;br /&gt;
=== 27 билет. Недетерминированные алгоритмы консенсуса. Алгоритм Бен-Ора. ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Алгоритм Бен-Ора]]&lt;br /&gt;
&lt;br /&gt;
=== 28-29 билеты. Paxos. Алгоритм, его свойства. Общие принципы. Основные модификации.===&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Paxos]]&lt;br /&gt;
&lt;br /&gt;
=== 30 билет. Raft. Алгоритм, его свойства.===&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Raft]]&lt;br /&gt;
&lt;br /&gt;
=== 31 билет. Транзакции в распределенных системах. 2 Phase Locking===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Locking]]&lt;br /&gt;
&lt;br /&gt;
=== 32 билет. Транзакции в распределенных системах. 2 Phase Commit.===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Commit]]&lt;br /&gt;
&lt;br /&gt;
=== 33 билет. СAP теорема (концепции, подходы, без доказательства)===&lt;br /&gt;
* [[CAP теорема]]&lt;br /&gt;
&lt;br /&gt;
=== 34 билет. Gossip. СRDT и дельта-CRDT (концепции, примеры алгоритмов, см. работу с семинара)===&lt;br /&gt;
* [[Gossip-протоколы]]&lt;br /&gt;
* [[CRDT]]&lt;br /&gt;
&lt;br /&gt;
=== 35 билет. Самостабилизирующиеся алгоритмы. Идея. Алгоритмы взаимного исключения и поиска остовного дерева ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Самостабилизирующиеся алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71613</id>
		<title>Параллельное программирование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71613"/>
				<updated>2019-06-04T06:06:13Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* 28-29 билеты. Paxos. Алгоритм, его свойства. Общие принципы. Основные модификации. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
=Программирование параллельных и распределенных систем=&lt;br /&gt;
*[[Базовые определения и формализм]]&lt;br /&gt;
*[[Алгоритмы взаимного исключения]]&lt;br /&gt;
*[[Стек Трайбера]]&lt;br /&gt;
*[[Формализм распределённых систем]]&lt;br /&gt;
&lt;br /&gt;
==6 семестр==&lt;br /&gt;
===Введение. Масштабируемость распределенных и параллельных систем, закон Амдала. Отличия распределенных систем от систем с разделяемой памятью===&lt;br /&gt;
*[[Параллельное программирование: Распределенные вычислительные системы|Распределенные системы]]&lt;br /&gt;
*[[Параллельное программирование: Масштабируемость параллельных и распределенных систем|Масштабируемость параллельных и распределенных систем]]&lt;br /&gt;
*[[Параллельное программирование: Закон Амдала| Закон Амдала]]&lt;br /&gt;
&lt;br /&gt;
===1-2 билеты. Логические часы Лампорта и векторные часы, их свойства===&lt;br /&gt;
*[[Параллельное программирование: Частичный порядок| Частичный порядок]]&lt;br /&gt;
*[[Параллельное программирование: Логические часы Лампорта| Логические часы Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Векторные часы| Векторные часы]]&lt;br /&gt;
&lt;br /&gt;
===3-4 билеты. Часы с прямой зависимостью (и их свойства) и матричные часы===&lt;br /&gt;
*[[Параллельное программирование: Часы с прямой зависимостью|Часы с прямой зависимостью]]&lt;br /&gt;
*[[Параллельное программирование: Матричные часы|Матричные часы]] (билет весной 2019 года убран)&lt;br /&gt;
&lt;br /&gt;
===5-7 билеты. Взаимное исключение в распределенной системе. Централизованный, алгоритм Лампорта, алгоритм Рикарта и Агравалы===&lt;br /&gt;
*[[Параллельное программирование: Централизованный алгоритм взаимного исключения|Централизованный алгоритм]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Лампорта взаимного исключения|Алгоритм Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Рикарта-Агравалы|Алгоритм Рикарта-Агравалы]]&lt;br /&gt;
&lt;br /&gt;
===8-10 билеты. Взаимное исключение в распределенной системе. Алгоритм обедающих философов, на основе токена, на основе кворума (простое большинство, рушащиеся стены)===&lt;br /&gt;
&lt;br /&gt;
*[[Задача обедающих философов]]&lt;br /&gt;
*[[Кворум]]&lt;br /&gt;
*[[Кворум простого большинства]]&lt;br /&gt;
*[[Кворум рушащейся стенки]]&lt;br /&gt;
&lt;br /&gt;
===11-12 билеты. Согласованное глобальное состояние (согласованный срез). Алгоритм Чанди-Лампорта. Запоминание сообщений на стороне отправителя и получателя===&lt;br /&gt;
&lt;br /&gt;
*[[Срез, согласованный срез]]&lt;br /&gt;
*[[Алгоритм Чанди-Лампорта]]&lt;br /&gt;
&lt;br /&gt;
===13-14 билеты. Глобальные свойства. Стабильные и нестабильные предикаты. Слабый конъюнктивный предикат. Централизованный и распределенный алгоритмы===&lt;br /&gt;
&lt;br /&gt;
*[[Глобальные свойства системы]]&lt;br /&gt;
*[[Слабый конъюнктивный предикат (WCP)]]&lt;br /&gt;
*[[Централизованный алгоритм для WCP]]&lt;br /&gt;
*[[Распределенный алгоритм для WCP]]&lt;br /&gt;
&lt;br /&gt;
===15 билет. Диффундирующие вычисления. Останов. Алгоритм Дейкстры и Шолтена===&lt;br /&gt;
* [[Диффундирующие вычисления]]&lt;br /&gt;
* [[Алгоритм Дейкстры и Шолтена]]&lt;br /&gt;
&lt;br /&gt;
===16 билет. Локально-стабильные предикаты, согласованные интервалы, барьерная синхронизация (3 алгоритма). Применение для определения взаимной блокировки===&lt;br /&gt;
&lt;br /&gt;
*[[Локально стабильный предикат]]&lt;br /&gt;
*[[Согласованный интервал]]&lt;br /&gt;
*[[Барьерная синхронизация (3 алгоритма)]]&lt;br /&gt;
*[[Определение взаимной блокировки]]&lt;br /&gt;
&lt;br /&gt;
===17-19 билеты. Упорядочивание сообщений. Определения, иерархия порядков. Алгоритм для FIFO. Алгоритм для причинно-согласованного порядка. Алгоритм для синхронного порядка ===&lt;br /&gt;
* [[Иерархия порядков сообщений]]&lt;br /&gt;
* [[Алгоритм для FIFO порядка]]&lt;br /&gt;
* [[Алгоритм для причинно-согласованного порядка]]&lt;br /&gt;
* [[Алгоритм для синхронного порядка]]&lt;br /&gt;
&lt;br /&gt;
===20-21 билеты. Общий порядок (total order). Алгоритмы Лампорта и Скина===&lt;br /&gt;
*[[Общий порядок сообщений]]&lt;br /&gt;
*[[Алгоритм Лампорта]]&lt;br /&gt;
*[[Алгоритм Скина]]&lt;br /&gt;
&lt;br /&gt;
===22 билет. Иерархия ошибок в распределенных системах. Отказ узла в асинхронной системе - невозможность консенсуса (доказательство Фишера-Линча-Патерсона)===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Теорема Фишера-Линча-Патерсона (FLP)]]&lt;br /&gt;
&lt;br /&gt;
===23 билет. Консенсус в распределенных системах. Применение консенсуса: выбор лидера, terminating reliable broadcast===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Переформулировки консенсуса в распределённой системе]]&lt;br /&gt;
&lt;br /&gt;
===24 билет. Синхронные системы. Алгоритм для консенсуса в случае отказа заданного числа узлов===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Консенсус в синхронных системах]]&lt;br /&gt;
&lt;br /&gt;
===25 билет. Синхронные системы. Проблема византийских генералов. Алгоритм для N &amp;gt;= 4, f = 1. Объяснить идею обобщения для f &amp;gt; 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Алгоритм Лампорта-Шостака-Пиза]] для решения проблемы&lt;br /&gt;
&lt;br /&gt;
===26 билет. Синхронные системы. Проблема византийских генералов. Невозможность решения при N = 3, f = 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Невозможность византийского консенсуса]] при N=3, f=1.&lt;br /&gt;
&lt;br /&gt;
=== 27 билет. Недетерминированные алгоритмы консенсуса. Алгоритм Бен-Ора. ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Алгоритм Бен-Ора]]&lt;br /&gt;
&lt;br /&gt;
=== 28-29 билеты. Paxos. Алгоритм, его свойства. Общие принципы. Основные модификации.===&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Paxos]]&lt;br /&gt;
&lt;br /&gt;
=== 30 билет. Raft. Алгоритм, его свойства.===&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Raft]]&lt;br /&gt;
&lt;br /&gt;
=== 31 билет. Транзакции в распределенных системах. 2 Phase Locking===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Locking]]&lt;br /&gt;
&lt;br /&gt;
=== 32 билет. Транзакции в распределенных системах. 2 Phase Commit.===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Commit]]&lt;br /&gt;
&lt;br /&gt;
=== 33 билет. СAP теорема (концепции, подходы, без доказательства)===&lt;br /&gt;
* [[CAP теорема]]&lt;br /&gt;
&lt;br /&gt;
=== 34 билет. Gossip. СRDT и дельта-CRDT (концепции, примеры алгоритмов, см. работу с семинара)===&lt;br /&gt;
* [[Gossip-протоколы]]&lt;br /&gt;
* [[CRDT]]&lt;br /&gt;
&lt;br /&gt;
=== 35 билет. Самостабилизирующиеся алгоритмы. Идея. Алгоритмы взаимного исключения и поиска остовного дерева ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Самостабилизирующиеся алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71612</id>
		<title>Параллельное программирование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71612"/>
				<updated>2019-06-04T06:05:38Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* 30 билет. Raft. Алгоритм, его свойства. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
=Программирование параллельных и распределенных систем=&lt;br /&gt;
*[[Базовые определения и формализм]]&lt;br /&gt;
*[[Алгоритмы взаимного исключения]]&lt;br /&gt;
*[[Стек Трайбера]]&lt;br /&gt;
*[[Формализм распределённых систем]]&lt;br /&gt;
&lt;br /&gt;
==6 семестр==&lt;br /&gt;
===Введение. Масштабируемость распределенных и параллельных систем, закон Амдала. Отличия распределенных систем от систем с разделяемой памятью===&lt;br /&gt;
*[[Параллельное программирование: Распределенные вычислительные системы|Распределенные системы]]&lt;br /&gt;
*[[Параллельное программирование: Масштабируемость параллельных и распределенных систем|Масштабируемость параллельных и распределенных систем]]&lt;br /&gt;
*[[Параллельное программирование: Закон Амдала| Закон Амдала]]&lt;br /&gt;
&lt;br /&gt;
===1-2 билеты. Логические часы Лампорта и векторные часы, их свойства===&lt;br /&gt;
*[[Параллельное программирование: Частичный порядок| Частичный порядок]]&lt;br /&gt;
*[[Параллельное программирование: Логические часы Лампорта| Логические часы Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Векторные часы| Векторные часы]]&lt;br /&gt;
&lt;br /&gt;
===3-4 билеты. Часы с прямой зависимостью (и их свойства) и матричные часы===&lt;br /&gt;
*[[Параллельное программирование: Часы с прямой зависимостью|Часы с прямой зависимостью]]&lt;br /&gt;
*[[Параллельное программирование: Матричные часы|Матричные часы]] (билет весной 2019 года убран)&lt;br /&gt;
&lt;br /&gt;
===5-7 билеты. Взаимное исключение в распределенной системе. Централизованный, алгоритм Лампорта, алгоритм Рикарта и Агравалы===&lt;br /&gt;
*[[Параллельное программирование: Централизованный алгоритм взаимного исключения|Централизованный алгоритм]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Лампорта взаимного исключения|Алгоритм Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Рикарта-Агравалы|Алгоритм Рикарта-Агравалы]]&lt;br /&gt;
&lt;br /&gt;
===8-10 билеты. Взаимное исключение в распределенной системе. Алгоритм обедающих философов, на основе токена, на основе кворума (простое большинство, рушащиеся стены)===&lt;br /&gt;
&lt;br /&gt;
*[[Задача обедающих философов]]&lt;br /&gt;
*[[Кворум]]&lt;br /&gt;
*[[Кворум простого большинства]]&lt;br /&gt;
*[[Кворум рушащейся стенки]]&lt;br /&gt;
&lt;br /&gt;
===11-12 билеты. Согласованное глобальное состояние (согласованный срез). Алгоритм Чанди-Лампорта. Запоминание сообщений на стороне отправителя и получателя===&lt;br /&gt;
&lt;br /&gt;
*[[Срез, согласованный срез]]&lt;br /&gt;
*[[Алгоритм Чанди-Лампорта]]&lt;br /&gt;
&lt;br /&gt;
===13-14 билеты. Глобальные свойства. Стабильные и нестабильные предикаты. Слабый конъюнктивный предикат. Централизованный и распределенный алгоритмы===&lt;br /&gt;
&lt;br /&gt;
*[[Глобальные свойства системы]]&lt;br /&gt;
*[[Слабый конъюнктивный предикат (WCP)]]&lt;br /&gt;
*[[Централизованный алгоритм для WCP]]&lt;br /&gt;
*[[Распределенный алгоритм для WCP]]&lt;br /&gt;
&lt;br /&gt;
===15 билет. Диффундирующие вычисления. Останов. Алгоритм Дейкстры и Шолтена===&lt;br /&gt;
* [[Диффундирующие вычисления]]&lt;br /&gt;
* [[Алгоритм Дейкстры и Шолтена]]&lt;br /&gt;
&lt;br /&gt;
===16 билет. Локально-стабильные предикаты, согласованные интервалы, барьерная синхронизация (3 алгоритма). Применение для определения взаимной блокировки===&lt;br /&gt;
&lt;br /&gt;
*[[Локально стабильный предикат]]&lt;br /&gt;
*[[Согласованный интервал]]&lt;br /&gt;
*[[Барьерная синхронизация (3 алгоритма)]]&lt;br /&gt;
*[[Определение взаимной блокировки]]&lt;br /&gt;
&lt;br /&gt;
===17-19 билеты. Упорядочивание сообщений. Определения, иерархия порядков. Алгоритм для FIFO. Алгоритм для причинно-согласованного порядка. Алгоритм для синхронного порядка ===&lt;br /&gt;
* [[Иерархия порядков сообщений]]&lt;br /&gt;
* [[Алгоритм для FIFO порядка]]&lt;br /&gt;
* [[Алгоритм для причинно-согласованного порядка]]&lt;br /&gt;
* [[Алгоритм для синхронного порядка]]&lt;br /&gt;
&lt;br /&gt;
===20-21 билеты. Общий порядок (total order). Алгоритмы Лампорта и Скина===&lt;br /&gt;
*[[Общий порядок сообщений]]&lt;br /&gt;
*[[Алгоритм Лампорта]]&lt;br /&gt;
*[[Алгоритм Скина]]&lt;br /&gt;
&lt;br /&gt;
===22 билет. Иерархия ошибок в распределенных системах. Отказ узла в асинхронной системе - невозможность консенсуса (доказательство Фишера-Линча-Патерсона)===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Теорема Фишера-Линча-Патерсона (FLP)]]&lt;br /&gt;
&lt;br /&gt;
===23 билет. Консенсус в распределенных системах. Применение консенсуса: выбор лидера, terminating reliable broadcast===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Переформулировки консенсуса в распределённой системе]]&lt;br /&gt;
&lt;br /&gt;
===24 билет. Синхронные системы. Алгоритм для консенсуса в случае отказа заданного числа узлов===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Консенсус в синхронных системах]]&lt;br /&gt;
&lt;br /&gt;
===25 билет. Синхронные системы. Проблема византийских генералов. Алгоритм для N &amp;gt;= 4, f = 1. Объяснить идею обобщения для f &amp;gt; 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Алгоритм Лампорта-Шостака-Пиза]] для решения проблемы&lt;br /&gt;
&lt;br /&gt;
===26 билет. Синхронные системы. Проблема византийских генералов. Невозможность решения при N = 3, f = 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Невозможность византийского консенсуса]] при N=3, f=1.&lt;br /&gt;
&lt;br /&gt;
=== 27 билет. Недетерминированные алгоритмы консенсуса. Алгоритм Бен-Ора. ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Алгоритм Бен-Ора]]&lt;br /&gt;
&lt;br /&gt;
=== 28-29 билеты. Paxos. Алгоритм, его свойства. Общие принципы. Основные модификации.===&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Paxos]]&lt;br /&gt;
&lt;br /&gt;
=== 30 билет. Raft. Алгоритм, его свойства.===&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Raft]]&lt;br /&gt;
&lt;br /&gt;
=== 31 билет. Транзакции в распределенных системах. 2 Phase Locking===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Locking]]&lt;br /&gt;
&lt;br /&gt;
=== 32 билет. Транзакции в распределенных системах. 2 Phase Commit.===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Commit]]&lt;br /&gt;
&lt;br /&gt;
=== 33 билет. СAP теорема (концепции, подходы, без доказательства)===&lt;br /&gt;
* [[CAP теорема]]&lt;br /&gt;
&lt;br /&gt;
=== 34 билет. Gossip. СRDT и дельта-CRDT (концепции, примеры алгоритмов, см. работу с семинара)===&lt;br /&gt;
* [[Gossip-протоколы]]&lt;br /&gt;
* [[CRDT]]&lt;br /&gt;
&lt;br /&gt;
=== 35 билет. Самостабилизирующиеся алгоритмы. Идея. Алгоритмы взаимного исключения и поиска остовного дерева ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Самостабилизирующиеся алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71611</id>
		<title>Replicated State Machine</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Replicated_State_Machine&amp;diff=71611"/>
				<updated>2019-06-04T06:02:56Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: Новая страница: «'''Replicated State Machine''' — система, которая хранит некий автомат (state machine) распределённо, а польз…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Replicated State Machine''' — система, которая хранит некий автомат (state machine) распределённо, а пользователи могут применять к этому автомату операции.&lt;br /&gt;
После этого RSM обязана эту операцию либо атомарно применить, либо откатить, и сообщить об этом пользователю.&lt;br /&gt;
Подтверждённые пользователю транзакции теряться не должны.&lt;br /&gt;
&lt;br /&gt;
Это может быть полезно, когда у нас есть очень важные данные, которые надо:&lt;br /&gt;
# Защитить от сбоев любого конкретного узла (т.е. надо хранить на нескольких узлах и нельзя иметь центрального координатора)&lt;br /&gt;
# Быстро обновлять (т.е. нельзя просто записывать на диск каждый раз)&lt;br /&gt;
&lt;br /&gt;
Если операции, применяемые к состоянию, детерминированы, то можно не клонировать состояние между машинами, а просто применять операции повторно на разных узлах.&lt;br /&gt;
Но операции обычно не коммутируют, поэтому всем узлам надо приходить к консенсусу: какие операции в каком порядке применять.&lt;br /&gt;
&lt;br /&gt;
Теоретически эта задача считается эквивалентной задаче консенсуса, поэтому действуют ограничения [[Теорема Фишера-Линча-Патерсона (FLP)|FLP]].&lt;br /&gt;
Нам обязательно нужна защита от отказов (иначе непонятно, зачем клонировать автомат),&lt;br /&gt;
рандом из [[Алгоритм Бен-Ора|алгоритма Бен-Ора]] &amp;quot;не сильно спасает&amp;quot; (как говорилось на лекции; вероятно, тут подразумевается его тормознутость),&lt;br /&gt;
а надеяться на синхронность системы на практике не хочется (&amp;quot;вдруг сообщение придёт не скоро?&amp;quot; с лекции).&lt;br /&gt;
По этому поводу мы обычно жертвуем завершением за конечное время: алгоритм [[Paxos]].&lt;br /&gt;
&lt;br /&gt;
Однако на практике могут возникать дополнительные сложности с тем, что узлы у нас не падают навсегда, а временно уходят и поднимаются обратно (т.е. [[Иерархия ошибок в распределённых системах|с точки зрения теории]] у нас ненадёжная доставка сообщений), а нам надо консенсус запускать несколько раз и ещё как-то доносить старые решения до вернувшихся узлов (чтобы на них тоже получилось корректное состояние).&lt;br /&gt;
В алгоритме [[Raft]] это отдельно разбирается.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%91%D0%B5%D0%BD-%D0%9E%D1%80%D0%B0&amp;diff=71610</id>
		<title>Алгоритм Бен-Ора</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%91%D0%B5%D0%BD-%D0%9E%D1%80%D0%B0&amp;diff=71610"/>
				<updated>2019-06-04T05:57:49Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
Алгоритм Бен-Ора — алгоритм, который позволяет $N$ процессам в асинхронной системе прийти к недетерминированному консенсусу на одном бите, если у нас не более $f&amp;lt;\frac N 2$ отказов узлов даже при ''сильном противнике'' за ожидаемое время $O(2^N)$.&lt;br /&gt;
&lt;br /&gt;
Мы хотим, чтобы процессы пришли к консенсусу.&lt;br /&gt;
Мы можем разрешить процессам кидать монетку, тем самым добавив недетерминизм и обойдя ограничения [[Теорема Фишера-Линча-Патерсона (FLP)|FLP]] на невозможность консенсуса.&lt;br /&gt;
&lt;br /&gt;
== Модель ==&lt;br /&gt;
Состояний у нас бесконечно, поэтому надо как-то уточнить требование завершимости: скажем, что мы хотим достигнуть консенсуса не за конечное время, а с вероятностью 1 (см. теорию меры для формальных определений).&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что в каждой конфигурации мы теперь находимся лишь с какой-то вероятностью,&lt;br /&gt;
порядок доставки сообщений всё ещё выбирает противник, чтобы нам было посложнее.&lt;br /&gt;
Бывает принципиально два вида противников:&lt;br /&gt;
* '''Сильный противник''' знает всё, что происходило в системе и всех процессах, включая полученные случайные биты, но не может предсказать будущее.&lt;br /&gt;
* '''Слабый противник''' чего-то может и не знать. Например, может видеть только сообщения и не знать ни полученных битов, ни внутренние состояния процессов.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Бен-Ора работает даже с сильным противником.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Каждый процесс работает бесконечно долго, алгоритм делится на одинаковые '''раунды''', пронумерованные натуральными числами с единицы.&lt;br /&gt;
&lt;br /&gt;
Каждый раунд состоит из двух '''фаз'''.&lt;br /&gt;
В каждой фазе процесс посылает всем остальным сообщение.&lt;br /&gt;
Важно, что система всё равно '''асинхронная''', поэтому для завершения фазы мы&lt;br /&gt;
ждём хотя бы $N-f$ ответов (а такое обязательно произойдёт, потому что у нас не более $f$ отказов),&lt;br /&gt;
а не какое-то &amp;quot;время&amp;quot; (которого нет).&lt;br /&gt;
&lt;br /&gt;
Каждое сообщение содержит в себе номер раунда, так что если пришло сообщение со старого раунда, оно игнорируется.&lt;br /&gt;
Если пришло с нового — ставится в очередь.&lt;br /&gt;
Вроде нам даже FIFO не требуется(?).&lt;br /&gt;
&lt;br /&gt;
В каждый момент у процесса есть '''предпочтение''' — бит.&lt;br /&gt;
&lt;br /&gt;
'''Первая фаза''': процесс рассылает всем остальным своё предпочтение: сообщение $(1, k, p)$, где $k$ — это номер раунда, а $p$ — предпочтение.&lt;br /&gt;
После получения $N-f$ ответов фаза завершается:&lt;br /&gt;
* Если процесс получил строго больше $\frac N 2$ предпочтений (включая своё) с каким-то значением, то это предложение '''ратифицируется'''.&lt;br /&gt;
&lt;br /&gt;
'''Вторая фаза''': если у процесса есть ратифицированное на данном шаге предпочтение, то он рассылает всем остальным&lt;br /&gt;
сообщение $(2, k, v)$ для ратификации ($v$ — ратифицированное значение).&lt;br /&gt;
В противном случае рассылает всем сообщение $(2, k, ?)$.&lt;br /&gt;
После получения $N-f$ ответов фаза завершается:&lt;br /&gt;
* Если процесс получил хотя бы одну ратификацию (или сам её отправил), то в следующем раунде предпочтение процесса меняется на полученное ратифицированное кем-то значение (все ратификации совпадают, см. ниже).&lt;br /&gt;
* Если процесс получил строго больше $f$ ратификаций, процесс принимает соответствующее ратифицированное решение, но продолжает выполняться в следующих раундах&lt;br /&gt;
* Если процесс не получил ни одной ратификации, предпочтение в следующем раунде меняется на случайный бит (это единственное '''недетерминированное место''')&lt;br /&gt;
&lt;br /&gt;
=== Доказательство ===&lt;br /&gt;
'''Лемма''': в каждом раунде $k$ все ратифицированные значения одинаковы.&lt;br /&gt;
Это очевидно, так как для ратификации требуется набрать строгое большинство предложений.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': если в раунде $k$ процесс $P$ принял решение $v$, то раунд $k+1$ все процессы начнут с предпочтением $v$.&lt;br /&gt;
Доказательство: чтобы принять решение, надо было получить хотя бы $f+1$ ратификацию.&lt;br /&gt;
Предположим, что какой-нибудь другой процесс $Q$, который начал следующий раунд не с предпочтением $v$.&lt;br /&gt;
Чтобы это произошло, $Q$ должен был не получить ни одной ратификации, то есть получить $N-f$ сообщений вида $(2, k, ?)$.&lt;br /&gt;
Но тогда всего в системе было $(f+1)+N-f=N+1&amp;gt;N$ сообщений, противоречие.&lt;br /&gt;
&lt;br /&gt;
Таким образом, если когда-то решение и приняли, то в следующем раунде у нас предпочтение у всех процессов равно этому решению, после чего&lt;br /&gt;
им остаётся только проголосовать за него, единогласно ратифицировать и решить.&lt;br /&gt;
&lt;br /&gt;
=== Остановка алгоритма ===&lt;br /&gt;
Когда какой-нибудь процесс принимает решение, он может разослать всем остальным сообщение &amp;quot;Решение принято&amp;quot; и остановиться.&lt;br /&gt;
Это сообщение дойдёт до всех живых процессов за конечное время, после чего они тоже остановятся.&lt;br /&gt;
То, что они будут пытаться достучаться до остановившихся процессов или общаться между собой, нам неважно.&lt;br /&gt;
&lt;br /&gt;
=== Оценки ===&lt;br /&gt;
Без доказательства.&lt;br /&gt;
Но у нас есть недетерминированный алгоритм в асинхронной системе с сильным противником с вероятностью завершения за конечное число шагов, равной единице.&lt;br /&gt;
Правда, среднее время работы экспоненциально: $O(2^N)$, потому что нам надо, чтобы случайными флуктуациями получилось достаточно много одинаковых битов.&lt;br /&gt;
Примерная причина: мы хотим случайно получить ситуацию, в которой есть больше $\frac N 2$ одинаковых битов из каких-то $N - f$, которые нам подсунул противник).&lt;br /&gt;
&lt;br /&gt;
Алгоритм не очень практичный, но интересный: показывает, как использовать монетку.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%A4%D0%B8%D1%88%D0%B5%D1%80%D0%B0-%D0%9B%D0%B8%D0%BD%D1%87%D0%B0-%D0%9F%D0%B0%D1%82%D0%B5%D1%80%D1%81%D0%BE%D0%BD%D0%B0_(FLP)&amp;diff=71609</id>
		<title>Теорема Фишера-Линча-Патерсона (FLP)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0_%D0%A4%D0%B8%D1%88%D0%B5%D1%80%D0%B0-%D0%9B%D0%B8%D0%BD%D1%87%D0%B0-%D0%9F%D0%B0%D1%82%D0%B5%D1%80%D1%81%D0%BE%D0%BD%D0%B0_(FLP)&amp;diff=71609"/>
				<updated>2019-06-04T05:49:43Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
Теорема Фишера, Линча и Патерсона (FLP, 1985 год): невозможно достичь даже необоснованного [[Консенсус в распределённой системе|консенсуса]] $N&amp;gt;2$ процессами даже на одном бите при следующих условиях:&lt;br /&gt;
* Алгоритм должен завершиться за конечное время.&lt;br /&gt;
* Один из узлов [[Иерархия ошибок в распределённых системах|может отказать]]&lt;br /&gt;
* Система [[Асинхронные и синхронные распределённые системы|асинхронна]]&lt;br /&gt;
* Алгоритм должен быть детерминирован.&lt;br /&gt;
&lt;br /&gt;
Если разрешаем незавершаемость в случае отказов, есть [[Paxos]] и [[Raft]].&lt;br /&gt;
Если отказов нет, есть [[Консенсус в распределённой системе#Решение при отсутствии отказов|простой алгоритм]].&lt;br /&gt;
Если система синхронна, то есть [[консенсус в синхронных системах]].&lt;br /&gt;
Если разрешаем недетерминизм, то есть [[алгоритм Бен-Ора]].&lt;br /&gt;
&lt;br /&gt;
При этом даже если разрешить одновременную посылку сообщения сразу нескольким процессам (как в [[Общий порядок сообщений|общем порядке сообщений]]) и тем самым запретить процессу падать при массовой рассылке сообщений, лучше не станет: нет гарантии, в каком порядке и как скоро эти сообщения будут получены и обработаны получателями.&lt;br /&gt;
А вот если какую-нибудь гарантию дадим, то получаем [[Переформулировки консенсуса в распределённой системе#Terminating Reliable Broadcast (TRB)|TLB]], из которого сразу выводится консенсус.&lt;br /&gt;
&lt;br /&gt;
== Доказательство ==&lt;br /&gt;
Из презентации Р. Елизарова.&lt;br /&gt;
&lt;br /&gt;
От противного: пусть есть такой алгоритм, тогда мы проанализируем варианты его исполнения, подстроим порядок доставки сообщений (без откладывания сообщений бесконечно далеко), получим бесконечную цепочку выполнения и противоречие с конечностью алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Модель ===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Процесс''' — это детерминированный автомат, который может выполнять три операции:&lt;br /&gt;
* &amp;lt;code&amp;gt;receive() : msg&amp;lt;/code&amp;gt; — бесконечная блокировка до получения ближайшего сообщения. Так как система асинхронна, возможности &amp;quot;посмотреть следующее сообщение&amp;quot; или ''таймаутов нет''.&lt;br /&gt;
* &amp;lt;code&amp;gt;send(msg)&amp;lt;/code&amp;gt; — отправка сообщения другому процессу. Гарантируется, что сообщение дойдёт получателю за конечное время, но это время может быть сколь угодно большим.&lt;br /&gt;
* &amp;lt;code&amp;gt;decided(value)&amp;lt;/code&amp;gt; — процесс принял решение &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;. Решение процесс может принять только один раз, но после этого он ''может продолжить выполняться'' и помогать остальным процессам.&lt;br /&gt;
Заметим, что так как нет &amp;quot;времени&amp;quot;, можно считать все переходы в процессе мгновенными.&lt;br /&gt;
}}&lt;br /&gt;
Для доказательства от противного у нас есть такой алгоритм для процессов, что все они вызывают &amp;lt;code&amp;gt;decided(value)&amp;lt;/code&amp;gt; с одинаковым значением через конечное время, независимо от того, как система задерживает сообщения.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Конфигурация''' — это состояния всех процессов плюс все сообщения в пути (которые отправили, но ещё не доставили).&lt;br /&gt;
}}&lt;br /&gt;
В начальной конфигурация у каждого процесса может быть сколько угодно входных данных и даже своя программа.&lt;br /&gt;
Начальных конфигураций может быть несколько, они могут отличаться, например, предложениями процессов.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Шаг''' из одной конфигурации в другую — это приём какого-то сообщения процессом (событие) и последовавшие за этим внутренние действия процесса до следующего &amp;lt;code&amp;gt;receive()&amp;lt;/code&amp;gt;. Эти действия ''однозначно'' определяются предыдущей конфигурацией и событием.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Исполнение''' — это ''бесконечная'' цепочка шагов из какой-нибудь начальной конфигурации. Бесконечная, потому что процессы могут выполняться и после принятия решений.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Отказавший процесс''' — это процесс, который делает только конечное количество шагов в исполнении. Такой в системе может быть максимум один (это более сильное условие, чем если может много процессов отказывать).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Также гарантируется, что в любом исполнении любое сообщение, предназначенное не отказавшему процессу, обрабатывается через конечное число шагов.&lt;br /&gt;
Другими словами, ''сообщения не теряются''.&lt;br /&gt;
&lt;br /&gt;
=== Валентность ===&lt;br /&gt;
Заметим, что в любом исполнении всегда принимается решение.&lt;br /&gt;
Даже если один процесс отказал, то все остальные должны прийти к решению за конечное число шагов.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Конфигурация называется '''$i$-валентной''' и '''одновалентной''', если все цепочки шагов из неё приводят к решению $i$.&lt;br /&gt;
Таким образом, бывают 0-валентные и 1-валентные конфигурации.&lt;br /&gt;
Если же из конфигурации есть цепочки, приводящие к каждому из решений, то такая конфигурация называется '''бивалентной'''.&lt;br /&gt;
}}&lt;br /&gt;
'''Наблюдение''': пусть из конфигурации $X$ есть цепочка шагов, обрабатывающая сообщения из $X$ в подмножестве процессов $A$, за которой идёт цепочка процессов, обрабатывающая сообщения из $X$ в подмножестве процессов $B$, и в конце мы получили конфигурацию $Y$. Тогда эти цепочки коммутируют: можно сначала обработать сообщения подмножеством процессов $B$, а потом — $A$ (так как мы обрабатываем только сообщения из $X$, а не новые).&lt;br /&gt;
&lt;br /&gt;
'''Наблюдение''': за $i$-валентной конфигурацией могут следовать только $i$-валентные.&lt;br /&gt;
&lt;br /&gt;
=== Начальная бивалентная конфигурация ===&lt;br /&gt;
'''Лемма''': существует бивалентная начальная конфигурация.&lt;br /&gt;
&lt;br /&gt;
Доказательство от противного: пусть все начальные конфигурации одновалентны.&lt;br /&gt;
Из нетривиальности консенсуса мы знаем, что есть как 0-, так и 1-валентные начальные конфигурации.&lt;br /&gt;
Тогда можно найти две начальные конфигурации разной валентности, которые отличаются только состоянием одного процесса:&lt;br /&gt;
взяли две произвольные начальные конфигурации разной валентности, начали переводить одну в другую копированием исходных состояний процессов, по одному процессу за шаг.&lt;br /&gt;
&lt;br /&gt;
А раз есть две такие конфигурации разной валентности, то пусть в каждой из них этот процесс (где они отличаются) откажет с самого начала, до отправки и приёма любых сообщений.&lt;br /&gt;
Тогда мы всё ещё получим консенсус, но решение будет одинаковым, потому что внешняя система никак не может выявить состояние отказавшего процесса.&lt;br /&gt;
А они исходно были разной валентности, противоречие.&lt;br /&gt;
&lt;br /&gt;
=== Цепочка бивалентных конфигураций ===&lt;br /&gt;
'''Лемма''': для любой бивалентной конфигурации можно найти следующую за ней бивалентную.&lt;br /&gt;
&lt;br /&gt;
'''Следствие''': если лемма верна, то мы можем построить бесконечную цепочку бивалентных конфигураций и тем самым получим противоречие и докажем FLP: есть бесконечная цепочка, в которой не принято решение.&lt;br /&gt;
&lt;br /&gt;
'''Доказательство''': от противного.&lt;br /&gt;
Пусть все конфигурации после некотороый бивалентной конфигурации $G$ одновалентны.&lt;br /&gt;
Введём определения:&lt;br /&gt;
* $e$ — какое-то событие в $G$, скармливающее сообщение $m$ процессу $p$. Такое есть, иначе у нас в конфигурации ничего не происходит, она бивалентна, а решение должно быть детерминированным, противоречие.&lt;br /&gt;
* $C$ — множество конфигураций, достижимых из $G$ без использования $e$. В частности, в $C$ по предположению отсутствуют бивалентные конфигурации.&lt;br /&gt;
* $D=e(C)$, то есть все конфигурации, достижимые из $G$, где $e$ — последнее обработанное событие. В частности, в $D$ по предположению отсутствуют бивалентные конфигурации.&lt;br /&gt;
Теперь докажем, что $D$ содержит бивалентную конфигурацию.&lt;br /&gt;
То есть мы выбрали, насколько сильно отложить обработку произвольного события $e$ и показали, что это не порушит бивалентность.&lt;br /&gt;
Надо ещё аккуратно, чтобы это не порушило конечность обработки каждого сообщения.&lt;br /&gt;
Например, их можно обрабатывать по очереди, начиная с самых старых.&lt;br /&gt;
Тогда каждое событие рано или поздно попадёт в наш шаг и будет обработано.&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-flp-proof-cd.png|500px]]&lt;br /&gt;
&lt;br /&gt;
==== Шаг 1: существование $i$-валентных конфигураций в $D$ ====&lt;br /&gt;
'''Подлемма''': для любого $i$ в $D$ существует $i$-валентная конфигурация.&lt;br /&gt;
&lt;br /&gt;
В самом деле: так как $G$ бивалентна, то по какой-то цепочке шагов из неё можно дойти до $i$-валентной конфигурации $E_i$.&lt;br /&gt;
Дальше разбором случаев находим искомую конфигурацию в $D$:&lt;br /&gt;
* Если $E_i \in D$, то мы доказали подлемму.&lt;br /&gt;
* Если $E_i \in C$, то $e(E_i) \in D$, у $e(E_i)$ такая же валентность и мы снова доказали подлемму.&lt;br /&gt;
* Иначе ребро $e$ применялось в цепочке шагов для достижения $E_i$ из $G$. Найдём конфигурацию $F_i \in D$, которая была в этой цепочке шагов сразу после применения $e$. Так как в $D$ нет бивалентных конфигураций, то $F_i$ является $i$-валентной, что и требовалось.&lt;br /&gt;
&lt;br /&gt;
==== Шаг 2: существование соседних разновалентных конфигураций ====&lt;br /&gt;
&lt;br /&gt;
Теперь мы хотим найти такие две соседние конфигурации $C_0, C_1 \in C$ (отличающиеся переходом $e'(C_0)=C_1$), что $D_0=e(C_0) \in D$ является 0-валентной, а $D_1=e(C_1)$ — 1-валентной (или наоборот).&lt;br /&gt;
Это можно сделать, если взять в $D$ конфигурацию $e(C_1)$, отличающуюся от валентности $e(G)$, а дальше посмотреть на цепочку конфигураций между $G$ и $e(C_1)$ и найти момент смены валентности.&lt;br /&gt;
&lt;br /&gt;
Начнём искать, более строго. Не теряя общности можем сказать, что $e(G)\in D$ является 0-валентной (иначе повторим доказательство шага).&lt;br /&gt;
По предыдущему шагу найдём в $D$ 1-валентную конфигурацию $D_1=e(C_1)\in D$.&lt;br /&gt;
Конфигурация $C_1$ получена какой-то конечной непустой цепочкой сообщений $x_1, x_2, \dots, x_k$.&lt;br /&gt;
Будем по очереди убирать по одному сообщения с конца и смотреть на валентность конфигураций $e(x_{k-1}(\dots(x_1(G))\dots))$, $e(x_{k-2}(\dots(x_1(G))\dots))$, \dots — в какой-то момент она сменится с единицы на ноль (например, при пустой цепочке, т.е. при рассмотрении $e(G)\in D$).&lt;br /&gt;
Тогда мы как раз нашли искомую пару соседей $C_0$ и $C_1$ таких, что $e(C_0)$ и $e(C_1)$ разной валентности.&lt;br /&gt;
&lt;br /&gt;
==== Шаг 3: разбор случаев ====&lt;br /&gt;
Теперь у нас, помимо конфигурации $C$ и события $e$, есть некоторое событие $e'$ и конфигурации $C_0$ и $C_1$, причём:&lt;br /&gt;
* $e(C_0)=D_0$ является 0-валентной, а $e(C_1)=D_1$ является 1-валентной (или наоборот, повторим доказательство)&lt;br /&gt;
* $e'(C_0)=C_1$&lt;br /&gt;
&lt;br /&gt;
Разберём два случая, в зависимости от того, одному процессу приходят $e$ и $e'$ или разным.&lt;br /&gt;
&lt;br /&gt;
===== Разным =====&lt;br /&gt;
Пусть $proc(e)\neq proc(e')$ (т.е. эти события в разных процессах).&lt;br /&gt;
Тогда нам всё равно, в каком порядке их обрабатывать, т.е. $e'(e(C_0))=e(e'(C_0))=e(C_1)=D_1$:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-flp-proof-case1.png|300px]]&lt;br /&gt;
&lt;br /&gt;
Мы знаем, что $D_1$ является 1-валентной. Но так как они достижима из $D_0$, то она также является и 0-валентной, противоречие.&lt;br /&gt;
&lt;br /&gt;
===== Одному =====&lt;br /&gt;
Пусть $proc(e) = proc(e') = p$ (т.е. это два сообщения одному и тому же процессу).&lt;br /&gt;
Тогда рассмотрим цепочку шагов $\sigma$ от состояния $C_0$, в которой процесс $p$ вообще отказал вместо обработки сообщений.&lt;br /&gt;
Тогда остальные процессы в этой цепочке пришли к какому-то решению в конфигурации $A=\sigma(C_0)$.&lt;br /&gt;
Тогда эта конфигурация должна быть либо 0-, либо 1-валентной (в ней уже принято решение).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-flp-proof-case2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Но теперь мы можем сказать, что процесс $p$ не отказал, а просто очень долго работал и теперь получает событие $e$.&lt;br /&gt;
Так как $\sigma$ не обращается к $p$, то $E_0=e(\sigma(C_0)=\sigma(e(C_0))=\sigma(D_0)$ — конфигурация, достижимая из 0-валентной, т.е. тоже 0-валентная.&lt;br /&gt;
&lt;br /&gt;
С другой стороны, можно аналогично сказать, что процесс $p$ теперь получает сообщение $e'$, а за ним — сообщение $e$.&lt;br /&gt;
Тогда получается $E_1=e(e'(\sigma(C_0))$.&lt;br /&gt;
Из-за коммутативности получаем $E_1=\sigma(e(e'(C_0)))=\sigma(e(C_1))=\sigma(D_1)$ — конфигурация, достижимая из 1-валентной, т.е. тоже 1-валентная.&lt;br /&gt;
&lt;br /&gt;
Таким образом получаем, что из $A$ достижимы и 0-валентная, и 1-валентная конфигурация, противоречие.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* http://bailonga.es/tpmtp/lecture09.pdf &lt;br /&gt;
* https://github.com/volhovm/study-notes/blob/master/parallel_programming/parallel_programming.org&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71608</id>
		<title>Параллельное программирование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71608"/>
				<updated>2019-06-04T05:34:32Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* 6 семестр */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
=Программирование параллельных и распределенных систем=&lt;br /&gt;
*[[Базовые определения и формализм]]&lt;br /&gt;
*[[Алгоритмы взаимного исключения]]&lt;br /&gt;
*[[Стек Трайбера]]&lt;br /&gt;
*[[Формализм распределённых систем]]&lt;br /&gt;
&lt;br /&gt;
==6 семестр==&lt;br /&gt;
===Введение. Масштабируемость распределенных и параллельных систем, закон Амдала. Отличия распределенных систем от систем с разделяемой памятью===&lt;br /&gt;
*[[Параллельное программирование: Распределенные вычислительные системы|Распределенные системы]]&lt;br /&gt;
*[[Параллельное программирование: Масштабируемость параллельных и распределенных систем|Масштабируемость параллельных и распределенных систем]]&lt;br /&gt;
*[[Параллельное программирование: Закон Амдала| Закон Амдала]]&lt;br /&gt;
&lt;br /&gt;
===1-2 билеты. Логические часы Лампорта и векторные часы, их свойства===&lt;br /&gt;
*[[Параллельное программирование: Частичный порядок| Частичный порядок]]&lt;br /&gt;
*[[Параллельное программирование: Логические часы Лампорта| Логические часы Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Векторные часы| Векторные часы]]&lt;br /&gt;
&lt;br /&gt;
===3-4 билеты. Часы с прямой зависимостью (и их свойства) и матричные часы===&lt;br /&gt;
*[[Параллельное программирование: Часы с прямой зависимостью|Часы с прямой зависимостью]]&lt;br /&gt;
*[[Параллельное программирование: Матричные часы|Матричные часы]] (билет весной 2019 года убран)&lt;br /&gt;
&lt;br /&gt;
===5-7 билеты. Взаимное исключение в распределенной системе. Централизованный, алгоритм Лампорта, алгоритм Рикарта и Агравалы===&lt;br /&gt;
*[[Параллельное программирование: Централизованный алгоритм взаимного исключения|Централизованный алгоритм]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Лампорта взаимного исключения|Алгоритм Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Рикарта-Агравалы|Алгоритм Рикарта-Агравалы]]&lt;br /&gt;
&lt;br /&gt;
===8-10 билеты. Взаимное исключение в распределенной системе. Алгоритм обедающих философов, на основе токена, на основе кворума (простое большинство, рушащиеся стены)===&lt;br /&gt;
&lt;br /&gt;
*[[Задача обедающих философов]]&lt;br /&gt;
*[[Кворум]]&lt;br /&gt;
*[[Кворум простого большинства]]&lt;br /&gt;
*[[Кворум рушащейся стенки]]&lt;br /&gt;
&lt;br /&gt;
===11-12 билеты. Согласованное глобальное состояние (согласованный срез). Алгоритм Чанди-Лампорта. Запоминание сообщений на стороне отправителя и получателя===&lt;br /&gt;
&lt;br /&gt;
*[[Срез, согласованный срез]]&lt;br /&gt;
*[[Алгоритм Чанди-Лампорта]]&lt;br /&gt;
&lt;br /&gt;
===13-14 билеты. Глобальные свойства. Стабильные и нестабильные предикаты. Слабый конъюнктивный предикат. Централизованный и распределенный алгоритмы===&lt;br /&gt;
&lt;br /&gt;
*[[Глобальные свойства системы]]&lt;br /&gt;
*[[Слабый конъюнктивный предикат (WCP)]]&lt;br /&gt;
*[[Централизованный алгоритм для WCP]]&lt;br /&gt;
*[[Распределенный алгоритм для WCP]]&lt;br /&gt;
&lt;br /&gt;
===15 билет. Диффундирующие вычисления. Останов. Алгоритм Дейкстры и Шолтена===&lt;br /&gt;
* [[Диффундирующие вычисления]]&lt;br /&gt;
* [[Алгоритм Дейкстры и Шолтена]]&lt;br /&gt;
&lt;br /&gt;
===16 билет. Локально-стабильные предикаты, согласованные интервалы, барьерная синхронизация (3 алгоритма). Применение для определения взаимной блокировки===&lt;br /&gt;
&lt;br /&gt;
*[[Локально стабильный предикат]]&lt;br /&gt;
*[[Согласованный интервал]]&lt;br /&gt;
*[[Барьерная синхронизация (3 алгоритма)]]&lt;br /&gt;
*[[Определение взаимной блокировки]]&lt;br /&gt;
&lt;br /&gt;
===17-19 билеты. Упорядочивание сообщений. Определения, иерархия порядков. Алгоритм для FIFO. Алгоритм для причинно-согласованного порядка. Алгоритм для синхронного порядка ===&lt;br /&gt;
* [[Иерархия порядков сообщений]]&lt;br /&gt;
* [[Алгоритм для FIFO порядка]]&lt;br /&gt;
* [[Алгоритм для причинно-согласованного порядка]]&lt;br /&gt;
* [[Алгоритм для синхронного порядка]]&lt;br /&gt;
&lt;br /&gt;
===20-21 билеты. Общий порядок (total order). Алгоритмы Лампорта и Скина===&lt;br /&gt;
*[[Общий порядок сообщений]]&lt;br /&gt;
*[[Алгоритм Лампорта]]&lt;br /&gt;
*[[Алгоритм Скина]]&lt;br /&gt;
&lt;br /&gt;
===22 билет. Иерархия ошибок в распределенных системах. Отказ узла в асинхронной системе - невозможность консенсуса (доказательство Фишера-Линча-Патерсона)===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Теорема Фишера-Линча-Патерсона (FLP)]]&lt;br /&gt;
&lt;br /&gt;
===23 билет. Консенсус в распределенных системах. Применение консенсуса: выбор лидера, terminating reliable broadcast===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Переформулировки консенсуса в распределённой системе]]&lt;br /&gt;
&lt;br /&gt;
===24 билет. Синхронные системы. Алгоритм для консенсуса в случае отказа заданного числа узлов===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Консенсус в синхронных системах]]&lt;br /&gt;
&lt;br /&gt;
===25 билет. Синхронные системы. Проблема византийских генералов. Алгоритм для N &amp;gt;= 4, f = 1. Объяснить идею обобщения для f &amp;gt; 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Алгоритм Лампорта-Шостака-Пиза]] для решения проблемы&lt;br /&gt;
&lt;br /&gt;
===26 билет. Синхронные системы. Проблема византийских генералов. Невозможность решения при N = 3, f = 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Невозможность византийского консенсуса]] при N=3, f=1.&lt;br /&gt;
&lt;br /&gt;
=== 27 билет. Недетерминированные алгоритмы консенсуса. Алгоритм Бен-Ора. ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Алгоритм Бен-Ора]]&lt;br /&gt;
&lt;br /&gt;
=== 28-29 билеты. Paxos. Алгоритм, его свойства. Общие принципы. Основные модификации.===&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Paxos]]&lt;br /&gt;
&lt;br /&gt;
=== 30 билет. Raft. Алгоритм, его свойства.===&lt;br /&gt;
=== 31 билет. Транзакции в распределенных системах. 2 Phase Locking===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Locking]]&lt;br /&gt;
&lt;br /&gt;
=== 32 билет. Транзакции в распределенных системах. 2 Phase Commit.===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Commit]]&lt;br /&gt;
&lt;br /&gt;
=== 33 билет. СAP теорема (концепции, подходы, без доказательства)===&lt;br /&gt;
* [[CAP теорема]]&lt;br /&gt;
&lt;br /&gt;
=== 34 билет. Gossip. СRDT и дельта-CRDT (концепции, примеры алгоритмов, см. работу с семинара)===&lt;br /&gt;
* [[Gossip-протоколы]]&lt;br /&gt;
* [[CRDT]]&lt;br /&gt;
&lt;br /&gt;
=== 35 билет. Самостабилизирующиеся алгоритмы. Идея. Алгоритмы взаимного исключения и поиска остовного дерева ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Самостабилизирующиеся алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71607</id>
		<title>Параллельное программирование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%B0%D1%80%D0%B0%D0%BB%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=71607"/>
				<updated>2019-06-04T05:33:54Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* 28 билет. Paxos. Алгоритм, его свойства. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
=Программирование параллельных и распределенных систем=&lt;br /&gt;
*[[Базовые определения и формализм]]&lt;br /&gt;
*[[Алгоритмы взаимного исключения]]&lt;br /&gt;
*[[Стек Трайбера]]&lt;br /&gt;
*[[Формализм распределённых систем]]&lt;br /&gt;
&lt;br /&gt;
==6 семестр==&lt;br /&gt;
===Введение. Масштабируемость распределенных и параллельных систем, закон Амдала. Отличия распределенных систем от систем с разделяемой памятью===&lt;br /&gt;
*[[Параллельное программирование: Распределенные вычислительные системы|Распределенные системы]]&lt;br /&gt;
*[[Параллельное программирование: Масштабируемость параллельных и распределенных систем|Масштабируемость параллельных и распределенных систем]]&lt;br /&gt;
*[[Параллельное программирование: Закон Амдала| Закон Амдала]]&lt;br /&gt;
&lt;br /&gt;
===1-2 билеты. Логические часы Лампорта и векторные часы, их свойства===&lt;br /&gt;
*[[Параллельное программирование: Частичный порядок| Частичный порядок]]&lt;br /&gt;
*[[Параллельное программирование: Логические часы Лампорта| Логические часы Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Векторные часы| Векторные часы]]&lt;br /&gt;
&lt;br /&gt;
===3-4 билеты. Часы с прямой зависимостью (и их свойства) и матричные часы===&lt;br /&gt;
*[[Параллельное программирование: Часы с прямой зависимостью|Часы с прямой зависимостью]]&lt;br /&gt;
*[[Параллельное программирование: Матричные часы|Матричные часы]] (билет весной 2019 года убран)&lt;br /&gt;
&lt;br /&gt;
===5-7 билеты. Взаимное исключение в распределенной системе. Централизованный, алгоритм Лампорта, алгоритм Рикарта и Агравалы===&lt;br /&gt;
*[[Параллельное программирование: Централизованный алгоритм взаимного исключения|Централизованный алгоритм]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Лампорта взаимного исключения|Алгоритм Лампорта]]&lt;br /&gt;
*[[Параллельное программирование: Алгоритм Рикарта-Агравалы|Алгоритм Рикарта-Агравалы]]&lt;br /&gt;
&lt;br /&gt;
===8-10 билеты. Взаимное исключение в распределенной системе. Алгоритм обедающих философов, на основе токена, на основе кворума (простое большинство, рушащиеся стены)===&lt;br /&gt;
&lt;br /&gt;
*[[Задача обедающих философов]]&lt;br /&gt;
*[[Кворум]]&lt;br /&gt;
*[[Кворум простого большинства]]&lt;br /&gt;
*[[Кворум рушащейся стенки]]&lt;br /&gt;
&lt;br /&gt;
===11-12 билеты. Согласованное глобальное состояние (согласованный срез). Алгоритм Чанди-Лампорта. Запоминание сообщений на стороне отправителя и получателя===&lt;br /&gt;
&lt;br /&gt;
*[[Срез, согласованный срез]]&lt;br /&gt;
*[[Алгоритм Чанди-Лампорта]]&lt;br /&gt;
&lt;br /&gt;
===13-14 билеты. Глобальные свойства. Стабильные и нестабильные предикаты. Слабый конъюнктивный предикат. Централизованный и распределенный алгоритмы===&lt;br /&gt;
&lt;br /&gt;
*[[Глобальные свойства системы]]&lt;br /&gt;
*[[Слабый конъюнктивный предикат (WCP)]]&lt;br /&gt;
*[[Централизованный алгоритм для WCP]]&lt;br /&gt;
*[[Распределенный алгоритм для WCP]]&lt;br /&gt;
&lt;br /&gt;
===15 билет. Диффундирующие вычисления. Останов. Алгоритм Дейкстры и Шолтена===&lt;br /&gt;
* [[Диффундирующие вычисления]]&lt;br /&gt;
* [[Алгоритм Дейкстры и Шолтена]]&lt;br /&gt;
&lt;br /&gt;
===16 билет. Локально-стабильные предикаты, согласованные интервалы, барьерная синхронизация (3 алгоритма). Применение для определения взаимной блокировки===&lt;br /&gt;
&lt;br /&gt;
*[[Локально стабильный предикат]]&lt;br /&gt;
*[[Согласованный интервал]]&lt;br /&gt;
*[[Барьерная синхронизация (3 алгоритма)]]&lt;br /&gt;
*[[Определение взаимной блокировки]]&lt;br /&gt;
&lt;br /&gt;
===17-19 билеты. Упорядочивание сообщений. Определения, иерархия порядков. Алгоритм для FIFO. Алгоритм для причинно-согласованного порядка. Алгоритм для синхронного порядка ===&lt;br /&gt;
* [[Иерархия порядков сообщений]]&lt;br /&gt;
* [[Алгоритм для FIFO порядка]]&lt;br /&gt;
* [[Алгоритм для причинно-согласованного порядка]]&lt;br /&gt;
* [[Алгоритм для синхронного порядка]]&lt;br /&gt;
&lt;br /&gt;
===20-21 билеты. Общий порядок (total order). Алгоритмы Лампорта и Скина===&lt;br /&gt;
*[[Общий порядок сообщений]]&lt;br /&gt;
*[[Алгоритм Лампорта]]&lt;br /&gt;
*[[Алгоритм Скина]]&lt;br /&gt;
&lt;br /&gt;
===22 билет. Иерархия ошибок в распределенных системах. Отказ узла в асинхронной системе - невозможность консенсуса (доказательство Фишера-Линча-Патерсона)===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Теорема Фишера-Линча-Патерсона (FLP)]]&lt;br /&gt;
&lt;br /&gt;
===23 билет. Консенсус в распределенных системах. Применение консенсуса: выбор лидера, terminating reliable broadcast===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Переформулировки консенсуса в распределённой системе]]&lt;br /&gt;
&lt;br /&gt;
===24 билет. Синхронные системы. Алгоритм для консенсуса в случае отказа заданного числа узлов===&lt;br /&gt;
&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Консенсус в синхронных системах]]&lt;br /&gt;
&lt;br /&gt;
===25 билет. Синхронные системы. Проблема византийских генералов. Алгоритм для N &amp;gt;= 4, f = 1. Объяснить идею обобщения для f &amp;gt; 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Алгоритм Лампорта-Шостака-Пиза]] для решения проблемы&lt;br /&gt;
&lt;br /&gt;
===26 билет. Синхронные системы. Проблема византийских генералов. Невозможность решения при N = 3, f = 1===&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Проблема византийских генералов]]&lt;br /&gt;
* [[Невозможность византийского консенсуса]] при N=3, f=1.&lt;br /&gt;
&lt;br /&gt;
=== 27 билет. Недетерминированные алгоритмы консенсуса. Алгоритм Бен-Ора. ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Асинхронные и синхронные распределённые системы]]&lt;br /&gt;
* [[Консенсус в распределённой системе]]&lt;br /&gt;
* [[Алгоритм Бен-Ора]]&lt;br /&gt;
&lt;br /&gt;
=== 28 билет. Paxos. Алгоритм, его свойства.===&lt;br /&gt;
* [[Replicated State Machine]]&lt;br /&gt;
* [[Paxos]] (гарантии)&lt;br /&gt;
&lt;br /&gt;
=== 29 билет. Paxos. Общие принципы. Основные модификации.===&lt;br /&gt;
=== 30 билет. Raft. Алгоритм, его свойства.===&lt;br /&gt;
=== 31 билет. Транзакции в распределенных системах. 2 Phase Locking===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Locking]]&lt;br /&gt;
&lt;br /&gt;
=== 32 билет. Транзакции в распределенных системах. 2 Phase Commit.===&lt;br /&gt;
* [[Транзакции в распределённых системах]]&lt;br /&gt;
* [[2 Phase Commit]]&lt;br /&gt;
&lt;br /&gt;
=== 33 билет. СAP теорема (концепции, подходы, без доказательства)===&lt;br /&gt;
* [[CAP теорема]]&lt;br /&gt;
&lt;br /&gt;
=== 34 билет. Gossip. СRDT и дельта-CRDT (концепции, примеры алгоритмов, см. работу с семинара)===&lt;br /&gt;
* [[Gossip-протоколы]]&lt;br /&gt;
* [[CRDT]]&lt;br /&gt;
&lt;br /&gt;
=== 35 билет. Самостабилизирующиеся алгоритмы. Идея. Алгоритмы взаимного исключения и поиска остовного дерева ===&lt;br /&gt;
* [[Иерархия ошибок в распределённых системах]]&lt;br /&gt;
* [[Самостабилизирующиеся алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B8_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B&amp;diff=71606</id>
		<title>Асинхронные и синхронные распределённые системы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B8_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B&amp;diff=71606"/>
				<updated>2019-06-04T05:33:18Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
* Синхронные системы&lt;br /&gt;
** Известно, что любое сообщение либо доставляется за некоторое время $C$, либо полностью исчезает&lt;br /&gt;
** Тогда можно разбить выполнение алгоритма на фазы длиной $O(C)$: в начале фазы все процессы отправляют сообщения, потом ждут, а в конце знают, что получили все сообщения, которые только могли прийти&lt;br /&gt;
* Асинхронные системы&lt;br /&gt;
** Время передачи сообщения сверху не ограничено&lt;br /&gt;
** Но гарантируется, что если нет отказов, то сообщение рано или поздно дойдёт&lt;br /&gt;
** Мы принципиально не можем использовать таймауты, поэтому нельзя смотреть на время даже внутри одного процесса: он либо что-то делает внутри себя, либо ждёт очередного сообщения бесконечно долго.&lt;br /&gt;
&lt;br /&gt;
Асинхронную систему можно на практике попробовать(?) превратить в синхронную при помощи таймаутов: к каждому сообщению прикрепляем wall clock time (которое не может быть идеально синхронизировано в распределённой системе, но на практике хоть как-то можно, сбои не всегда играют против нас) и игнорируем слишком старые сообщения. Надо аккуратно поиграть с определениями и учесть погрешность и потребовать, чтобы часы не расходились, возможно, ещё что-то.&lt;br /&gt;
Выберем большой таймаут — будет тормозить, выберем маленький — будут большие потери сообщений.&lt;br /&gt;
&lt;br /&gt;
Если решили задачу для асинхронной системы, то в синхронной будет работать то же самое.&lt;br /&gt;
Но, возможно, для синхронной системы существует более эффективный или простой алгоритм.&lt;br /&gt;
Обратное тоже возможно: например, пока синхронная система будет ждать таймаута, асинхронная может быстро забить дожидаться ответа и всё сделать.&lt;br /&gt;
&lt;br /&gt;
На практике могут использоваться алгоритмы и для тех, и для других.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=2_Phase_Commit&amp;diff=71605</id>
		<title>2 Phase Commit</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=2_Phase_Commit&amp;diff=71605"/>
				<updated>2019-06-03T21:15:00Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Алгоритм двухфазного коммита''' — классический централизованный оптимистичный алгоритм распределённого консенсуса из баз данных для подтверждения [[Транзакции в распределённых системах|распределённых транзакций]].&lt;br /&gt;
&lt;br /&gt;
После того, как мы завершили транзакцию, её надо атомарно подтвердить на всех участниках (participants).&lt;br /&gt;
У каждой транзакции есть выделенный координатор (transaction coordinator).&lt;br /&gt;
Алгоритм работает в две фазы:&lt;br /&gt;
&lt;br /&gt;
# '''Запрос (request)''': координатор спрашивает каждого участника: &amp;quot;готов ли ты ''очень быстро и гарантированно'' завершить транзакцию?&amp;quot;. Если кто-нибудь ответил &amp;quot;нет&amp;quot;, то отменяем транзакцию. Если кто-то отвечает &amp;quot;да&amp;quot;, то он должен уметь обеспечить завершение транзакции даже если упадёт и поднимается (например, все данные уже в журнале).&lt;br /&gt;
# '''Завершение''': координатор принимает решение о закреплении (commit) или отмене (rollback) транзакции и записывает его в свою надёжную память, после чего рассылает всем решение. После рассылки можно сообщить о фиксации транзакции, подтверждения от участников ждать не нужно (но тогда может быть проблема с тем, что следующие чтения из СУБД будут возвращать старые данные, пока не закоммитили).&lt;br /&gt;
&lt;br /&gt;
При этом проблемы двух генералов на практике обычно нет: после того, как координатор принял решение о транзакции, он будет его доносить до всех любопытствующих узлов.&lt;br /&gt;
&lt;br /&gt;
Всего на коммит требуется $3N$ сообщений ($N$ — количество участников транзакции) и задержка порядка $3\cdot RTT$ (round-trip time).&lt;br /&gt;
&lt;br /&gt;
== Ограничения ==&lt;br /&gt;
Так как это алгоритм консенсуса, к нему применима [[Теорема Фишера-Линча-Патерсона (FLP)|FLP]].&lt;br /&gt;
&lt;br /&gt;
Если у нас есть отказы узлов или связи, то 2PC будет ждать, пока связь не восстановится:&lt;br /&gt;
* Если отказ произошёл на первой фазе, то координатор может отменить транзакцию по таймауту.&lt;br /&gt;
* После того, как координатор перешёл на вторую фазу, он не имеет права успокоиться, пока не донесёт своё решение до всех узлов.&lt;br /&gt;
* Если узел отказал, а потом восстановился, то он спрашивает координатора, какое решение было принято. Если &amp;quot;да&amp;quot;, то обязан закрепить транзакцию (т.е. координатор должен хранить все подтверждённые транзакции, которые подтвердили не все узлы).&lt;br /&gt;
* Если отказал координатор, то, если узел ответил &amp;quot;да&amp;quot;, он не имеет права забить на транзакцию, пока координатор не восстановится.&lt;br /&gt;
&lt;br /&gt;
Но алгоритм классический, простой, на практике неплохо работает, потому что сложно только с отказами координатора и отказами узлов на второй фазе (когда решение о коммите уже принято), а такое бывает не так часто.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BC%D0%BF%D0%BE%D1%80%D1%82%D0%B0-%D0%A8%D0%BE%D1%81%D1%82%D0%B0%D0%BA%D0%B0-%D0%9F%D0%B8%D0%B7%D0%B0&amp;diff=71604</id>
		<title>Алгоритм Лампорта-Шостака-Пиза</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BC%D0%BF%D0%BE%D1%80%D1%82%D0%B0-%D0%A8%D0%BE%D1%81%D1%82%D0%B0%D0%BA%D0%B0-%D0%9F%D0%B8%D0%B7%D0%B0&amp;diff=71604"/>
				<updated>2019-06-03T21:14:04Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* N=4, f=1 с лекции */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
Алгоритм Лампорта-Шостака-Пиза (1982) решает [[Проблема византийских генералов|проблему византийских генералов]]: если имеется $N$ процессов, среди которых не более $f$ византийских, причём $3f &amp;lt; N$, то они могут прийти к консенсусу за конечное время, используя надёжные каналы связи.&lt;br /&gt;
&lt;br /&gt;
== N=4, f=1 с лекции ==&lt;br /&gt;
В первой фазе все процессы шлют своё предложение всем остальным, во второй — пересылают все полученную информацию всем остальным, итого $2N^2$ сообщений.&lt;br /&gt;
&lt;br /&gt;
У каждого невизантийского процесса появляется матрица информации: кто кому что сказал.&lt;br /&gt;
Рассмотрим пример такой матрицы (процесс не знает, какой процесс византийский, мы пометили для демонстрации):&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-byzantine-4-1.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Диагональ вычёркиваем, нам эту информацию и так дали на первой фазе и ей нельзя верить в любом случае (например, так мы вычёркиваем $t_7$, что важно для доказательства ниже).&lt;br /&gt;
&lt;br /&gt;
В столбце византийского процесса находится что угодно, потому что он мог нам сказать что угодно (то есть $t_4$, $t_5$ и $t_6$ могут быть разные у всех процессов).&lt;br /&gt;
В строчке византийского процесса тоже находится что угодно, но одинаковое для всех процессов, потому что&lt;br /&gt;
содержимое этой строчки нам гарантированно рассказывают честные процессы (т.е. $t_1$, $t_2$ и $t_3$ одинаковые для всех процессов).&lt;br /&gt;
Так что большинство в строчке византийского процесса ($t$) непонятное, но одно для всех честных процессов.&lt;br /&gt;
&lt;br /&gt;
А в строчках нормальных процессов находятся константы, за исключением одного столбца от византийского процесса.&lt;br /&gt;
Таким образом, большинство в каждой строчке (кроме одной византийской) — это то, что соответствующий процесс реально рассылал ($x$, $y$, $z$).&lt;br /&gt;
&lt;br /&gt;
Следовательно, теперь у всех нормальных процессов множество из большинств по строкам одинаковое.&lt;br /&gt;
Можно применять детерминированную функцию для выбора консенсуса.&lt;br /&gt;
То есть византийский процесс не может помешать достигнуть консенсуса, но иногда может его изменить.&lt;br /&gt;
&lt;br /&gt;
== Идея общего случая с $f&amp;gt;1$ ==&lt;br /&gt;
Надо сделать ещё несколько стадий. &lt;br /&gt;
На первой рассылаем значения, на второй — матрицы, на третьей — кубики (мне прислали такую матрицу), и так далее.&lt;br /&gt;
На экзамене подробнее не требуется.&lt;br /&gt;
&lt;br /&gt;
Впрочем, описание в Garg (секция 15.4.2, страница 244) требует $N &amp;gt; 4f$, а не $N &amp;gt; 3f$.&lt;br /&gt;
&lt;br /&gt;
== Общий случай из старых конспектов ==&lt;br /&gt;
Считаем, что у процессов есть номера. Процесс 1 - &amp;quot;генерал&amp;quot; - рассылает всем предложение - 0 или 1. И после этого молчит (принимает своё предложение).&lt;br /&gt;
&lt;br /&gt;
При f=0 все остальные (&amp;quot;лейтенанты&amp;quot;) просто принимают предложение.&lt;br /&gt;
&lt;br /&gt;
При f=1 все &amp;quot;лейтенанты&amp;quot; рассылают всем &amp;quot;лейтенантам&amp;quot; сообщение &amp;quot;генерал сказал X&amp;quot;. Теперь у каждого процесса есть N-1 сообщение вида &amp;quot;A сказал, что генерал сказал X&amp;quot;, включая своё(Я сказал, что генерал сказал X). Выбираем вариант, который встречается больше раз, или 0 если одинаково. Если сбойный процесс - генерал, то все остальные процессы получат одинаковое количество 0 и 1 в сообщениях и выберут одинаковый вариант. Если сбойный процесс - лейтенант, все остальные процессы получат больше верных сообщений, чем неверных и выберут вариант, посланный генералом.&lt;br /&gt;
&lt;br /&gt;
При f=2+ делаем всего f раундов рассылки сообщений между лейтенантами (при f=2 посылаются сообщения &amp;quot;B сказал, что A сказал, что генерал сказал X&amp;quot;), и f раундов выбора большинства внутри каждого процесса (т.е. для f=2 процесс имеет N-1 сообщение &amp;quot;B сказал, что А сказал ...&amp;quot; и решает, что именно сказал A выбором варианта, который больше встречается).&lt;br /&gt;
&lt;br /&gt;
Если же все процессы равноправные, то в 0 раунде рассылки все считают себя &amp;quot;генералами&amp;quot;, а потом делаем консенсус на исходных значениях каждого.&lt;br /&gt;
&lt;br /&gt;
Выбор варианта в конечном итоге даст правильный вариант именно потому, что N &amp;gt; 3f.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BE%D0%BD%D1%81%D0%B5%D0%BD%D1%81%D1%83%D1%81_%D0%B2_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D0%BE%D0%B9_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B5&amp;diff=71603</id>
		<title>Консенсус в распределённой системе</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BE%D0%BD%D1%81%D0%B5%D0%BD%D1%81%D1%83%D1%81_%D0%B2_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D0%BE%D0%B9_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B5&amp;diff=71603"/>
				<updated>2019-06-03T21:13:35Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Решение при отсутствии отказов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Параллельное программирование]]&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Задача консенсуса''': есть N процессов, у каждого есть некие данные — предложение (proposal), они должны выполнить некоторый распределённый алгоритм и прийти к решению (decision). Требуется:&lt;br /&gt;
* Согласие (agreement): все не отказавшие (не упавшие навсегда) процессы должны завершиться с решением (decide) и все эти решения должны совпадать.&lt;br /&gt;
* Нетривиальность (non-triviality): должны быть варианты исполнения, приводящие к разным решениям (возможно, просто с разными исходными предложениями или разным исходным состоянием процессов).&lt;br /&gt;
}}&lt;br /&gt;
Также можно требовать завершение (termination): протокол должен завершиться за конечное время.&lt;br /&gt;
&lt;br /&gt;
Предложение/решение может быть битом, числом, чем-нибудь ещё — это всё друг к другу сводится.&lt;br /&gt;
Доказательств не было, они очень технические, есть в толстенной книжке Линча.&lt;br /&gt;
Но нужно примерно понимание, как сводить консенсус на бите к консенсусу на чём-нибудь сложном.&lt;br /&gt;
&lt;br /&gt;
Можно ещё требовать '''обоснованный''' консенсус: это когда принятое решение должно совпадать с одним из исходных предложений.&lt;br /&gt;
Необоснованный консенсус к обоснованному тоже сводится: сначала выбираем лидера (см. ниже), а потом лидер делает обоснованный выбор&lt;br /&gt;
(если возникают потери сообщений или падения, то всё тухло).&lt;br /&gt;
Формальное доказательство, опять же, опущено.&lt;br /&gt;
&lt;br /&gt;
== Решение при отсутствии отказов ==&lt;br /&gt;
&lt;br /&gt;
Каждый процесс рассылает всем остальным своё предложение.&lt;br /&gt;
Каждый процесс ждёт предложения остальных, после чего детерминированной функцией выбирает элемент из множества.&lt;br /&gt;
У остальных процессов получилось такое же множество, такая же функция, следовательно, такой же результат.&lt;br /&gt;
Работает даже в асинхронной системе, $N^2$ сообщений.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1%D0%BA%D0%B8%D0%BD%D0%B0&amp;diff=71602</id>
		<title>Алгоритм Скина</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1%D0%BA%D0%B8%D0%BD%D0%B0&amp;diff=71602"/>
				<updated>2019-06-03T21:13:17Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Алгоритм Скина'''&amp;lt;ref&amp;gt;https://doi.org/10.1109/TSE.1983.236608&amp;lt;/ref&amp;gt; для организации [[Общий порядок сообщений|общего порядка сообщений]].&lt;br /&gt;
Лучше, чем [[Алгоритм Лампорта]], потому что для multicast сообщений общается только с получателями, а не со всеми процессами системы.&lt;br /&gt;
&lt;br /&gt;
Используются [[Логические часы Лампорта|логические часы Лампорта]].&lt;br /&gt;
Ниже алгоритм расписан чуть подробнее, чем в Garg и на лекции, но вроде всё ещё верно.&lt;br /&gt;
&lt;br /&gt;
У каждого процесса есть очередь принятых необработанных multicast сообщений.&lt;br /&gt;
Каждое сообщение имеет временну́ю метку и флаг — финализирована ли метка.&lt;br /&gt;
&lt;br /&gt;
# Инициатор отправляет сообщение и своё время (''предварительное время сообщения'') всем получателям&lt;br /&gt;
# При приеме сообщения процесс запоминает сообщение со временем в очередь (как нефинализированное) и отправляет свое время инициатору&lt;br /&gt;
# Когда инициатору вернулись все подтверждения, он выбирает максимальное время из них и снова отправляет сообщение со финализированным временем&lt;br /&gt;
# Получатель может обработать сообщение, если оно помечено как финальное и имеет минимальное время среди всех известных получателю сообщений (и финальных, и нефинальных; иначе может получиться, что финализация сообщений произойдёт в разном порядке у разных получателей и нарушится общий порядок)&lt;br /&gt;
&lt;br /&gt;
Полный порядок задается финальными временными метками. Финальные метки нужны, чтобы как-то зависеть от времени получателей.&lt;br /&gt;
Доказательство на лекции и в Gaarg не приводилось.&lt;br /&gt;
&lt;br /&gt;
Итого $3(k-1)$ сообщений на каждый multicast на $k$ процессов (не обсуждалось на лекции, но вроде так).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D1%80%D1%8F%D0%B4%D0%BA%D0%B0&amp;diff=71601</id>
		<title>Алгоритм для синхронного порядка</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D1%80%D1%8F%D0%B4%D0%BA%D0%B0&amp;diff=71601"/>
				<updated>2019-06-03T21:12:24Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
Этот алгоритм берёт систему с асинхронным(?) порядком и начинает гарантировать в ней [[Иерархия порядков сообщений#Синхронный порядок|синхронный порядок]].&lt;br /&gt;
&lt;br /&gt;
Алгоритм для синхронного порядка основан на иерархии процессов (точнее, произвольном DAG процессов, отправлять сообщения могут только соединённые ребром), мы рассмотрим полный линейный порядок.&lt;br /&gt;
Упорядочим процессы по номеру, назовем сообщение ''большим'', если номер отправителя больше номера получателя, и ''малым'' иначе.&lt;br /&gt;
Процесс может быть в ''активном'' или ''пассивном состоянии''. Изначально все активны.&lt;br /&gt;
В пассивном состоянии процесс не может ни отправлять, ни получать сообщения, он их складывает в очередь и ждёт, пока не станет активным.&lt;br /&gt;
&lt;br /&gt;
Если процесс хочет отправить большое сообщение, то он его отправляет и ждёт подтверждения.&lt;br /&gt;
А пока ждёт — становится пассивным.&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-order-sync-algo-big.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Чтобы отправить сообщение большему процессу &amp;lt;tex&amp;gt;P_j&amp;lt;/tex&amp;gt;, процесс &amp;lt;tex&amp;gt;P_i&amp;lt;/tex&amp;gt; сначала посылает служебное сообщение, ''запрос''. В ответ &amp;lt;tex&amp;gt;P_j&amp;lt;/tex&amp;gt; отправляет ''разрешение''; он может сделать это только в активном состоянии. Разрешив, он становится пассивным и остается в этом состоянии, пока не получает сообщение, которое разрешил.&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-order-sync-algo-small.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, сообщения по факту &amp;quot;передаются&amp;quot; только от больших к маленьким и тогда можно нарисовать стрелочки.&lt;br /&gt;
Взаимная блокировка наступить не может: мы ждём только меньших процессов, а транзитивность у нас есть и циклов быть не может.&lt;br /&gt;
Если маленький хочет отправить сообщение большому, то он отсылает запрос и продолжает работать (посылать большие и маленькие сообщения, менять своё состояние).&lt;br /&gt;
Ничего страшного, что по факту сообщение &amp;quot;отправится&amp;quot; только через какое-то время — с точки зрения процесса оно просто долго было в пути.&lt;br /&gt;
&lt;br /&gt;
Разумеется, надо аккуратно доказать, что функцию $T$ можно придумать. Это делается на странице 200 в Gaarg, там происходит что-то вроде логических часов.&lt;br /&gt;
&lt;br /&gt;
Итого на $m$ сообщений нам требуется послать не больше $3m$ сообщений (худший случай — все сообщения маленькие).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%B0%D1%80%D1%8C%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_(3_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%B0)&amp;diff=71600</id>
		<title>Барьерная синхронизация (3 алгоритма)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%B0%D1%80%D1%8C%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_(3_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%B0)&amp;diff=71600"/>
				<updated>2019-06-03T21:10:53Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Алгоритмы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
== Определение и полезность ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Интервал &amp;lt;tex&amp;gt;[G, H]&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;G \subseteq H&amp;lt;/tex&amp;gt;) называется '''барьерно-синхронизированным''', если для любых событий &amp;lt;tex&amp;gt;e \in G&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f \notin H&amp;lt;/tex&amp;gt; верно, что $e \rightarrow f$.&lt;br /&gt;
}}&lt;br /&gt;
Другими словами, все события слева от интервала произошло до всех событий справа от интервала.&lt;br /&gt;
Это сильнее [[Согласованный интервал|согласованных интервалов]]: те требуют лишь отсутствия стрелок справа налево (коих в барьере не может быть, потому что есть вообще все возможные стрелки слева направо, а в две стороны стрелки не бывает).&lt;br /&gt;
&lt;br /&gt;
Как следствие, внутри любого барьерно-сихнронизированного интервала тоже есть согласованный срез (где-то, не знаем, где).&lt;br /&gt;
А искать такой интервал намного проще, чем [[Алгоритм Чанди-Лампорта|искать согласованный срез]] и по коду, и по количеству сообщений (линия вместо квадрата).&lt;br /&gt;
&lt;br /&gt;
== Алгоритмы ==&lt;br /&gt;
&lt;br /&gt;
*[[Централизованный]]: все посылают токен координатору, затем он посылает всем. &amp;lt;tex&amp;gt;2N&amp;lt;/tex&amp;gt; сообщений, низкая задержка;&lt;br /&gt;
* Каждый посылает каждому токен. &amp;lt;tex&amp;gt;N^2&amp;lt;/tex&amp;gt; сообщений, низкая задержка;&lt;br /&gt;
* Token по кольцу два раза, &amp;lt;tex&amp;gt;2N-1&amp;lt;/tex&amp;gt; сообщение, высокая задержка (вроде можно $2N-2$ сообщений).&lt;br /&gt;
[[Файл:Token_ring.png|200px|thumb|left]]&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%B0%D1%80%D1%8C%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_(3_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%B0)&amp;diff=71599</id>
		<title>Барьерная синхронизация (3 алгоритма)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%B0%D1%80%D1%8C%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_(3_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%B0)&amp;diff=71599"/>
				<updated>2019-06-03T21:09:47Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Алгоритмы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
== Определение и полезность ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Интервал &amp;lt;tex&amp;gt;[G, H]&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;G \subseteq H&amp;lt;/tex&amp;gt;) называется '''барьерно-синхронизированным''', если для любых событий &amp;lt;tex&amp;gt;e \in G&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;f \notin H&amp;lt;/tex&amp;gt; верно, что $e \rightarrow f$.&lt;br /&gt;
}}&lt;br /&gt;
Другими словами, все события слева от интервала произошло до всех событий справа от интервала.&lt;br /&gt;
Это сильнее [[Согласованный интервал|согласованных интервалов]]: те требуют лишь отсутствия стрелок справа налево (коих в барьере не может быть, потому что есть вообще все возможные стрелки слева направо, а в две стороны стрелки не бывает).&lt;br /&gt;
&lt;br /&gt;
Как следствие, внутри любого барьерно-сихнронизированного интервала тоже есть согласованный срез (где-то, не знаем, где).&lt;br /&gt;
А искать такой интервал намного проще, чем [[Алгоритм Чанди-Лампорта|искать согласованный срез]] и по коду, и по количеству сообщений (линия вместо квадрата).&lt;br /&gt;
&lt;br /&gt;
== Алгоритмы ==&lt;br /&gt;
&lt;br /&gt;
*[[Централизованный]]: все посылают токен координатору, затем он посылает всем. &amp;lt;tex&amp;gt;2N&amp;lt;/tex&amp;gt; сообщений, низкая задержка;&lt;br /&gt;
* Каждый посылает каждому токен. &amp;lt;tex&amp;gt;N^2&amp;lt;/tex&amp;gt; сообщений, низкая задержка;&lt;br /&gt;
* Token по кольцу два раза, &amp;lt;tex&amp;gt;2N&amp;lt;/tex&amp;gt; сообщений, высокая задержка.&lt;br /&gt;
[[Файл:Token_ring.png|200px|thumb|left]]&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B_%D0%B8_%D0%A8%D0%BE%D0%BB%D1%82%D0%B5%D0%BD%D0%B0&amp;diff=71598</id>
		<title>Алгоритм Дейкстры и Шолтена</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B_%D0%B8_%D0%A8%D0%BE%D0%BB%D1%82%D0%B5%D0%BD%D0%B0&amp;diff=71598"/>
				<updated>2019-06-03T21:09:19Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
Алгоритм Дейкстры и Шолтена&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Dijkstra-Scholten_algorithm&amp;lt;/ref&amp;gt; решает задачу останова [[Диффундирующие вычисления|диффундирующего вычисления]] в распределённой системе.&lt;br /&gt;
&lt;br /&gt;
Основная идея: выстроить процессы в дерево: кто кого активизировал. Процесс добавляется в дерево (становится &amp;quot;красным&amp;quot;), когда становится активным, а удаляется (становится &amp;quot;зелёным&amp;quot;), когда он и все его потомки стали пассивными и там нет сообщений (т.е. поддерево закончило вычисления). Исходно дерево содержит только инициатора, а когда вычисление остановится, станет пустым (о чём узнает инициатор).&lt;br /&gt;
&lt;br /&gt;
Каждый процесс будет требовать подтверждения на каждое своё сообщение, чтобы можно было учесть сообщения в пути.&lt;br /&gt;
&lt;br /&gt;
Каждый процесс хранит внутри себя несколько чисел:&lt;br /&gt;
# Количество неподтверждённых сообщений остальным процессам. Увеличивается при отправке сообщения, кроме ack. Уменьшается при получении ack (у нас всё ещё не бывает ошибок и перепосылок, они дальше в билетах).&lt;br /&gt;
# Количество детей в дереве.&lt;br /&gt;
# Номер родительского процесса (null для инициатора, он же корень).&lt;br /&gt;
&lt;br /&gt;
Процесс называется ''зелёным'', если выполняются все следующие условия:&lt;br /&gt;
# Процесс пассивен (в смысле диффундирующего вычисления, в нашем алгоритме он всё ещё может общаться с остальными)&lt;br /&gt;
# Нет неподтверждённых сообщений другим процессам&lt;br /&gt;
# У него нет детей в дереве&lt;br /&gt;
&lt;br /&gt;
В противном случае процесс называется ''красным''.&lt;br /&gt;
Дерево состоит в точности из множества красных процессов.&lt;br /&gt;
Чтобы поддерживать этот инвариант, требуется задать поведение процессов:&lt;br /&gt;
* Зелёный процесс не отправляет никому сообщения&lt;br /&gt;
* Зелёный процесс остаётся зелёным, пока не получит сообщение (это не может быть ack, и это сообщение только от красного):&lt;br /&gt;
** При получении становится красным и новым листом в дереве&lt;br /&gt;
** Отсылает автору сообщения сообщения &amp;quot;я твой новый ребёнок&amp;quot;, после чего автор увеличивает количество своих детей&lt;br /&gt;
* Красный процесс может отправить сообщение другому красному, тогда никаких изменений состояния не происходит (только меняется счётчик неподтверждённых сообщений у отправителя)&lt;br /&gt;
* Красный процесс остаётся красным, пока не начинают выполняться условия для становления зелёным:&lt;br /&gt;
** Если процесс стал зелёным, он удаляет себя из дерева, послав родителю сообщения &amp;quot;я больше не твой ребёнок&amp;quot;, после чего родитель уменьшает количество своих детей&lt;br /&gt;
&lt;br /&gt;
Тогда диффундирующее вычисление заканчивается в точности когда корень дерева (инициатор) становится зелёным.&lt;br /&gt;
&lt;br /&gt;
Итого у нас получается $N$ процессов и $m$ сообщений в сумме требуется послать $2m+k\le 3m$ сообщений(?), где $k$ — количество раз, которые вершина становится красной:&lt;br /&gt;
* На каждое из $m$ сообщение идёт ответ: либо с пометкой &amp;quot;я твой новый ребёнок&amp;quot;, либо без пометки.&lt;br /&gt;
* Каждый раз, когда вершина становится красной, она должна в какой-то момент стать обратно зелёной и отправить родителю оповещение.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D0%B8%D0%BA%D0%B0%D1%80%D1%82%D0%B0-%D0%90%D0%B3%D1%80%D0%B0%D0%B2%D0%B0%D0%BB%D1%8B&amp;diff=71597</id>
		<title>Алгоритм Рикарта-Агравалы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D0%B8%D0%BA%D0%B0%D1%80%D1%82%D0%B0-%D0%90%D0%B3%D1%80%D0%B0%D0%B2%D0%B0%D0%BB%D1%8B&amp;diff=71597"/>
				<updated>2019-06-03T21:04:43Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Алгоритм Рикарта-Агравалы''' — алгоритм взаимного исключения, являющийся оптимизацией [[Алгоритм Лампорта взаимного исключения|алгоритма Лампорта]].&lt;br /&gt;
&lt;br /&gt;
Мы объединяем запросы rel и ok в один: вместо отправки ok сразу посылаем только если не хотим входить в критическую секцию или сразу как только выйдем из секции.&lt;br /&gt;
&lt;br /&gt;
# Когда процесс &amp;lt;tex&amp;gt;P_i&amp;lt;/tex&amp;gt; хочет войти в критический участок, то рассылает всем сообщение req с текущей временной меткой.&lt;br /&gt;
# Когда процесс &amp;lt;tex&amp;gt;P_k&amp;lt;/tex&amp;gt; получает от &amp;lt;tex&amp;gt;P_j&amp;lt;/tex&amp;gt; запрос войти в критический участок:&lt;br /&gt;
#* если он сам не посылал запрос, то посылает отклик;&lt;br /&gt;
#* если он послал свой запрос, он сравнивает временные метки этих двух запросов и посылает отклик только если у его собственного запроса метка позже (на самом деле, при равенстве меток, нужно проверять, у кого больше номер, т.е. для отсутствия блокировок нужно ввести приоритет на потоках);&lt;br /&gt;
#* в остальных случаях процесс &amp;lt;tex&amp;gt;P_k&amp;lt;/tex&amp;gt; задерживает отправку отклика.&lt;br /&gt;
# Процесс может войти в критический участок только после получения откликов ото всех других узлов сети.&lt;br /&gt;
# После выхода из него он рассылает задержанные отклики на все ожидающие запросы.&lt;br /&gt;
&lt;br /&gt;
В отличие от алгоритма Лапрота, нам не требуется ни третьего сообщения, ни хранить очередь запросов в каждом процессе.&lt;br /&gt;
&lt;br /&gt;
[[Файл:mutex-distributed-ricart.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Алгоритм является starvation-free. Суммарно на каждую критическую секцию приходится &amp;lt;tex&amp;gt;2 \cdot (N-1)&amp;lt;/tex&amp;gt; сообщений. &lt;br /&gt;
&lt;br /&gt;
Отказ любого узла приводит к зависанию. Решается проблема введением таймаутов.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71596</id>
		<title>Самостабилизирующиеся алгоритмы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71596"/>
				<updated>2019-06-03T21:02:37Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Самостабилизирующие алгоритмы''' — это идея построения алгоритмов, устойчивых к ошибкам:&lt;br /&gt;
* Код потерять сложно, поэтому мы считаем, что он не портится при падении узлов.&lt;br /&gt;
* Алгоритм может работать с любой комбинацией данных.&lt;br /&gt;
* Из любого состояния мы попадаем в '''легальное''' через конечное число шагов (при отсутствии сбоев).&lt;br /&gt;
}}&lt;br /&gt;
Тогда от ''любого'' сбоя мы через конечное число шагов будем восстанавливаться без консенсусов и прочих развлечений.&lt;br /&gt;
== Взаимное исключение ==&lt;br /&gt;
Dijkstra Stabilizing Token Ring Algorithm.&lt;br /&gt;
&lt;br /&gt;
Сначала надо переформулировать задачу: мы говорим, что каждый процесс в системе может либо '''иметь привилегию''', либо не иметь.&lt;br /&gt;
В произвольном состоянии системы привилегия может быть у произвольного количества процессов, но через конечное число шагов она остаётся только у одного процесса и мы входим в легальное состояние.&lt;br /&gt;
Дальше остаёмся только в легальных состояниях.&lt;br /&gt;
&lt;br /&gt;
TODO: а какие сообщения процессы посылают друг другу? Могут ли быть ошибки (наверное, нет)? Может ли система быть асинхронной (наверное, тоже нет)?&lt;br /&gt;
&lt;br /&gt;
Все $N$ процессов будут замкнуты в кольцо, в котором один процесс назван &amp;quot;первым&amp;quot;.&lt;br /&gt;
У каждого процесса есть состояние — число от 0 до $K-1$, причём $K \ge N$ — параметр алгоритма.&lt;br /&gt;
&lt;br /&gt;
По определению положим, что у процесса есть привилегия, если:&lt;br /&gt;
* Он первый и его значение $S$ совпадает со значением $L$ следующего по часовой стрелке процесса.&lt;br /&gt;
* Он не первый и его $S$ не совпадает с $L$.&lt;br /&gt;
&lt;br /&gt;
Например, на рисунке ниже толстая граница у выделенного процесса, а жёлтым обозначена привилегия:&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-self-stabilization-legal.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Правила перехода в новое состояние:&lt;br /&gt;
* Для первого процесса: если была привилегия ($S=L$), то переходим в состояние $(S + 1) \bmod K$&lt;br /&gt;
* Для не-первого процесса: если привилегия есть ($S \neq L$), то переходим в состояние $&lt;br /&gt;
Пример двух переходов:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-1.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, в легальном состоянии привилегия у нас ходит по кругу, как в алгоритме с токеном.&lt;br /&gt;
Но там потеря токена была смертельной для алгоритма, а у нас — не смертельна.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство стабилизируемости ===&lt;br /&gt;
'''Лемма''': в любом состоянии хотя бы у одного процесса есть привилегия.&lt;br /&gt;
В противном случае у нас, с одной стороны, все значения машин равны друг другу (потому что для каждой машины, кроме первой, её значение совпадает со следующей по кругу), а с другой стороны значение первой машины и её соседа должны отличаться, противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': что бы не происходило в системе, через $O(N^2)$ шагов в системе первый процесс сделает ход.&lt;br /&gt;
'''Доказательство (с лекции)''': если первый процесс не делает ход, то следующий за ним против часовой стрелки процесс 2 сможет сделать максимум один ход: взять себе значение первого процесса.&lt;br /&gt;
Процесс 3 после каждого хода процесса 2 может сделать максимум один ход: взять себе значение процесса 2.&lt;br /&gt;
То есть процесс 3 может сделать не больше двух ходов (один исходно, один после хода процесса 2).&lt;br /&gt;
Аналогично, процесс 4 может сделать не больше трёх ходов, и так далее.&lt;br /&gt;
Итого мы получаем, что если первый процесс не делает шаги, то через $O(N^2)$ шагов привилегия полностью исчезнет, чего не бывает.&lt;br /&gt;
&lt;br /&gt;
'''Альтернативное доказательство (проверено рандомом)''': если первый процесс может сделать ход сразу, то всё доказали. &lt;br /&gt;
Иначе у него нет привилегии.&lt;br /&gt;
Заметим, что если следующий за ним по часовой стрелке процесс 2 либо имеет значение, равное ему, либо отличающееся (тогда он имеет привилегию и сразу делает ход).&lt;br /&gt;
Таким образом, через один ход процессы 1 и 2 имеют одинаковые значения.&lt;br /&gt;
Аналогично, через два хода процессы 1, 2 и 3 имеют одинаковые значения.&lt;br /&gt;
А через $N-1$ шаг все процессы гарантированно имеют одинаковые значения (если первый процесс так и не походил).&lt;br /&gt;
Таким образом, через $N-1$ шаг у первого процесса появляется привилегия и он ходит, $N=O(N^2)$.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': рано или поздно у первого процесса будет уникальное $S$.&lt;br /&gt;
'''Доказательство''': все остальные процессы умеют только копировать состояния друг у друга, а первый процесс ходит бесконечно.&lt;br /&gt;
Поэтому рано или поздно он перейдёт на состояние, которое не совпадает ни с одним из оставшихся $N-1$ состоянием.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': через $O(N^2)$ после этого система стабилизируется.&lt;br /&gt;
'''Альтернативное доказательство (не с лекции)''': это состояние будет сразу же скопировано на второй процесс, потом сразу же скопировано на третий, и так далее, после чего мы прийдём в состояние, где все значения равны, а оно легальное.&lt;br /&gt;
&lt;br /&gt;
== Поиск остовного дерева ==&lt;br /&gt;
Такая задача возникает, например, в internet of things: набросали с вертолёта на поле размером 3км*3км много хрупких устройств со слабыми антеннами, которым надо соединиться в единую сеть. При этом топология связи там неполная и половина устройств подохла.&lt;br /&gt;
А мы хотим построить дерево, чтобы узлы могли друг с другом общаться (а не каждый каждому передавать, потому что тогда надо бороться с циклами).&lt;br /&gt;
&lt;br /&gt;
Решение начинается с инициатора (например, узел, которому надо что-нибудь узнать про всех остальных), которому это дерево нужно.&lt;br /&gt;
&lt;br /&gt;
Каждый узел поддерживает у себя $d$ (расстояние до корня) и $p$ (узел-предок в дереве).&lt;br /&gt;
Корень всегда ставит у себя $d=0$ и $p=-1$, а остальные узлы в постоянном режиме делают:&lt;br /&gt;
* Найти соседа $j$ с минимальным $d_j$&lt;br /&gt;
* Установить его в качестве своего родителя и $d_i=d_j+1$&lt;br /&gt;
&lt;br /&gt;
Тогда корень стабилизируется сразу, узлы, которым корень виден, стабилизируются через одну итерацию, их соседи — через две, и так далее.&lt;br /&gt;
&lt;br /&gt;
Если какой-нибудь узел выпадает, то его дети найдут себе кого-нибудь ещё и снова встроятся в дерево.&lt;br /&gt;
&lt;br /&gt;
Единственная проблема — если умирает корень, но тогда узнавший об этом узел может инициировать перестроение дерева (если у нас цель — связь).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Gossip-%D0%BF%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB%D1%8B&amp;diff=71595</id>
		<title>Gossip-протоколы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Gossip-%D0%BF%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB%D1%8B&amp;diff=71595"/>
				<updated>2019-06-03T21:02:34Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Gossip-протоколы''' — семейство протоколов, которые позволяют обеспечивать eventual consistency в распределённой системе.&lt;br /&gt;
В [[CAP-теорема|CAP-теореме]] они жертвуют согласованностью, получают доступность и устойчивость к разделению.&lt;br /&gt;
&lt;br /&gt;
Основная идея: узлы распространяют информацию об изменениях друг другу по мере возможности, причём не только самостоятельно добавленные изменения, но и то, что услышали от других узлов (слухи, gossip).&lt;br /&gt;
Тогда при отсутствии сбоев рано или поздно все узлы обо всём узнают.&lt;br /&gt;
Разумеется, могут появиться конфликты, их надо как-нибудь решать.&lt;br /&gt;
Можно либо спускать эту задачу на уровень приложения (Amazon Dynamo), либо использовать специальные конструкции для распространения слухов вроде [[CRDT]], которые не допускают конфликтов по построению.&lt;br /&gt;
&lt;br /&gt;
Точные протоколы общения процессов и распространения слухов мы не разбирали и они, говорят, не так важны.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=CAP_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0&amp;diff=71594</id>
		<title>CAP теорема</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=CAP_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D0%B0&amp;diff=71594"/>
				<updated>2019-06-03T21:02:27Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''CAP-теорема''' — утверждение о том, что в распределённых системах нельзя одновременно добиться трёх свойств:&lt;br /&gt;
* '''C'''onsistency — на всех ''не отказавших'' узлах одинаковые (с точки зрения пользователя) данные&lt;br /&gt;
* '''A'''vailability — запросы ко всем ''не отказавшим'' узлам возвращают ответ&lt;br /&gt;
* '''P'''artition tolerance — даже если связь в системе стала нестабильной (вплоть до разделения системы на куски), то система продолжает работать&lt;br /&gt;
&lt;br /&gt;
Формально мы это не формулировали и не доказывали.&lt;br /&gt;
Оригинальная формулировка — Brewer's Conjecture (2000), а формализовано в работе Gilbert &amp;amp; Lynch (2004).&lt;br /&gt;
Там есть много тонкостей с тем, что такое &amp;quot;не отказавший узел&amp;quot;, &amp;quot;одинаковые данные&amp;quot;, &amp;quot;разрыв связи&amp;quot;, &amp;quot;система продолжает работать&amp;quot;, &amp;quot;когда система всё-таки окончательно ломается и считается недоступной&amp;quot; и тому подобное.&lt;br /&gt;
&lt;br /&gt;
Для общей эрудиции выглядят неплохо статьи&amp;lt;ref&amp;gt;http://blog.thislongrun.com/2015/04/the-unclear-cp-vs-ca-case-in-cap.html&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;https://habr.com/ru/post/322276/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Классификация алгоритмов ==&lt;br /&gt;
А вот алгоритмы, которые удовлетворяют хотя бы двум свойствам, можно нарисовать на диаграмма Венна:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-cap.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Дальше идут объяснения с лекции, они отличаются в разных источниках (например, где-то 2PC идёт вместе с Paxos в CP, а не в CA&amp;lt;ref&amp;gt;http://www.cedanet.com.au/ceda/fallacies/cap-theorem.php&amp;lt;/ref&amp;gt;), а где-то совпадают с лекцией&amp;lt;ref&amp;gt;http://book.mixu.net/distsys/single-page.html#the-cap-theorem&amp;lt;/ref&amp;gt;, а где-то считают, что не-partition tolerance не нужно&amp;lt;ref&amp;gt;https://codahale.com/you-cant-sacrifice-partition-tolerance/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Если мы хотим согласованность и доступность, то используем [[2 Phase Commit|протокол двухфазного коммита]]: он гарантирует нам согласованное состояние глобально во всей системе и мы всегда можем обслуживать запросы. Но если потерялась связь, то какие-то запросы нельзя обработать, потому что часть данных может быть на одном узле, а часть на другом. Каждый кусок всё ещё будет работать по отдельности, но глобальные транзакции выполнять мы не сможем.&lt;br /&gt;
* Иногда нам не так важна согласованность и мы согласны на простую eventual consistency — это когда информация может быть доступна не сразу везде, а только через какое-то время, если система здорова. Сюда идут [[gossip-протоколы]].&lt;br /&gt;
* Если мы хотим согласованность и толерантность к разделению, то надо жертвовать доступностью. Например, при помощи Paxos мы можем хранить все данные сразу на всех узлах, но тогда узлы, оказавшиеся в меньшинстве, ничего сделать не могут.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=2_Phase_Commit&amp;diff=71593</id>
		<title>2 Phase Commit</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=2_Phase_Commit&amp;diff=71593"/>
				<updated>2019-06-03T21:02:23Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Алгоритм двухфазного коммита''' — классический централизованный оптимистичный алгоритм распределённого консенсуса из баз данных для подтверждения [[Транзакции в распределённых системах|распределённых транзакций]].&lt;br /&gt;
&lt;br /&gt;
После того, как мы завершили транзакцию, её надо атомарно подтвердить на всех участниках.&lt;br /&gt;
У каждой транзакции есть выделенный координатор (transaction coordinator).&lt;br /&gt;
Алгоритм работает в две фазы:&lt;br /&gt;
&lt;br /&gt;
# '''Запрос (request)''': координатор спрашивает каждого участника: &amp;quot;готов ли ты ''очень быстро и гарантированно'' завершить транзакцию?&amp;quot;. Если кто-нибудь ответил &amp;quot;нет&amp;quot;, то отменяем транзакцию. Если кто-то отвечает &amp;quot;да&amp;quot;, то он должен уметь обеспечить завершение транзакции даже если упадёт и поднимается (например, все данные уже в журнале).&lt;br /&gt;
# '''Завершение''': координатор принимает решение о закреплении (commit) или отмене (rollback) транзакции и записывает его в свою надёжную память, после чего рассылает всем решение. После рассылки можно сообщить о фиксации транзакции, подтверждения от участников ждать не нужно (но тогда может быть проблема с тем, что следующие чтения из СУБД будут возвращать старые данные, пока не закоммитили).&lt;br /&gt;
&lt;br /&gt;
При этом проблемы двух генералов на практике обычно нет: после того, как координатор принял решение о транзакции, он будет его доносить до всех любопытствующих узлов.&lt;br /&gt;
&lt;br /&gt;
== Ограничения ==&lt;br /&gt;
Так как это алгоритм консенсуса, к нему применима [[Теорема Фишера-Линча-Патерсона (FLP)|FLP]].&lt;br /&gt;
&lt;br /&gt;
Если у нас есть отказы узлов или связи, то 2PC будет ждать, пока связь не восстановится:&lt;br /&gt;
* Если отказ произошёл на первой фазе, то координатор может отменить транзакцию по таймауту.&lt;br /&gt;
* После того, как координатор перешёл на вторую фазу, он не имеет права успокоиться, пока не донесёт своё решение до всех узлов.&lt;br /&gt;
* Если узел отказал, а потом восстановился, то он спрашивает координатора, какое решение было принято. Если &amp;quot;да&amp;quot;, то обязан закрепить транзакцию (т.е. координатор должен хранить все подтверждённые транзакции, которые подтвердили не все узлы).&lt;br /&gt;
* Если отказал координатор, то, если узел ответил &amp;quot;да&amp;quot;, он не имеет права забить на транзакцию, пока координатор не восстановится.&lt;br /&gt;
&lt;br /&gt;
Но алгоритм классический, простой, на практике неплохо работает, потому что сложно только с отказами координатора и отказами узлов на второй фазе (когда решение о коммите уже принято), а такое бывает не так часто.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=2_Phase_Locking&amp;diff=71592</id>
		<title>2 Phase Locking</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=2_Phase_Locking&amp;diff=71592"/>
				<updated>2019-06-03T21:02:16Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Алгоритм двухфазной блокировки''' используется для взятия блокировок при выполнении [[Транзакции в распределённых системах|распределённых транзакций]] (например, в СУБД).&lt;br /&gt;
&lt;br /&gt;
Алгоритм требует, чтобы каждая транзакция должна состояла из двух фаз: на первой мы только набираем блокировки (в любом порядке), а на второй фазе мы их только отпускаем (в любом порядке).&lt;br /&gt;
Например, если мы работаем с элементами $x$ и $y$, то мы можем сначала взять блокировку на $x$, потом поработать с $x$, потом взять блокировку на $y$, поработать с ним, а потом отпустить все блокировки.&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-2pl.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Если все транзакции устроены таким образом, то гарантируется сериализуемость транзакции.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Так можно брать не все блокировки, а только нужные.&lt;br /&gt;
Это особенно удобно в СУБД, когда движок заранее не знает, какие блокировки потребуются: он может просто набирать блокировки, как появляются запросы, а в конце, при применении транзакции, их разом отпустить.&lt;br /&gt;
&lt;br /&gt;
Из-за этого могут возникнуть проблемы с взаимными блокировками (потому что порядок взятия блокировок может отличаться в разных транзакциях), поэтому:&lt;br /&gt;
* [[Определение взаимной блокировки|Детектор взаимных блокировок]] всё равно нужен. Если нашли — то отменяем одну из транзакций и снимаем все её блокировки. Есть разные стратегии выбора, какую транзакцию отменять. Можно самую новую (тогда мы будем дожидаться старой), можно самую долго работающую (тогда у коротких запросов приоритет), можно ещё как-то.&lt;br /&gt;
* В некоторых СУБД есть даже специальный SQL-синтаксис для deadlock avoidness, вроде &amp;lt;code&amp;gt;SELECT FOR UPDATE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Проблемы, конечно, в том, что если у нас большой запрос по всем строкам таблицы, то нам нужно всё заблокировать, но для этого есть [[Транзакции в распределённых системах#Согласованность и изоляция|MVCC]] или пониженные уровни изоляции.&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D0%B8_%D0%B2_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D1%85_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0%D1%85&amp;diff=71591</id>
		<title>Транзакции в распределённых системах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D0%B8_%D0%B2_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D1%85_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0%D1%85&amp;diff=71591"/>
				<updated>2019-06-03T21:02:12Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
== Зачем ==&lt;br /&gt;
&lt;br /&gt;
Пусть у нас есть несколько узлов (процессов), которых хранят какие-то ''непересекающиеся'' данные.&lt;br /&gt;
Например, на одном узле хранятся банковские счета пользователей на &amp;quot;А&amp;quot;, на другом — на &amp;quot;Б&amp;quot;, и так далее.&lt;br /&gt;
&lt;br /&gt;
Тогда мы можем хотеть транзакционно изменять данные на разных узлах (см. &amp;lt;code&amp;gt;BEGIN TRANSACTION&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;COMMIT TRANSACTION&amp;lt;/code&amp;gt; в SQL).&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Транзакция''' — это единица работы над множеством элементов из базы данных, которую можно в процессе работы целиком '''отменить''' (либо сама база данных, либо пользователь, см. &amp;lt;code&amp;gt;ROLLBACK TRANSACTION&amp;lt;/code&amp;gt;), либо '''подтвердить''' (база данных может иногда не справиться, тогда транзакция отменяется).&lt;br /&gt;
}}&lt;br /&gt;
У транзакции обычно выделяют свойства по аббревиатуре ACID:&lt;br /&gt;
# '''A'''tomicity (атомарность) — транзакция либо полностью '''применила''' все свои изменения, либо полностью '''откатилась''' (отменилась)&lt;br /&gt;
# '''C'''onsitency (согласованность) — в конце транзакции система находится в согласованном состоянии&lt;br /&gt;
# '''I'''solation (изолированность) — параллельные транзакции не должны влиять друг на друга (например, при помощи phantom reads и non-repeatable reads), а должны выполняться как будто последовательно&lt;br /&gt;
# '''D'''urability (надёжность) — завершённые (commited) транзакции сохраняются даже в случае сбоев и перезапуска системы&lt;br /&gt;
&lt;br /&gt;
== Атомарность и надёжность ==&lt;br /&gt;
Предположим, что нам нужны только атомарность и надёжность.&lt;br /&gt;
Самое сложное — откатывать транзакцию, если что-то пошло не так.&lt;br /&gt;
Есть два основных способа этого добиться.&lt;br /&gt;
&lt;br /&gt;
=== Undo log ===&lt;br /&gt;
Каждый узел сначала записывает предыдущие значения в надёжный журнал (лог, обычно append-only и сохраняется на диск), а только потом изменяет состояние в памяти.&lt;br /&gt;
Когда транзакция подтверждается, надо записать произведённые изменения в надёжное место и можно стереть кусок журнала.&lt;br /&gt;
Если транзакцию надо откатить (например, после перезапуска системы в журнале нет записи &amp;quot;транзакция успешна&amp;quot;), то мы идём с конца журнала и восстанавливаем старые значения.&lt;br /&gt;
&lt;br /&gt;
=== Redo log ===&lt;br /&gt;
Мы вообще не делаем изменения в данных до подтверждения транзакции, а просто пишем в журнал все операции, которые надо произвести с данными.&lt;br /&gt;
Когда транзакция успешно завершается, у нас две опции:&lt;br /&gt;
* Изменить данные прямо на диске.&lt;br /&gt;
* Записать об этом в журнал на диск (append-only), а состояние просто каждый раз восстанавливать из этого журнала. Иногда делать checkpoint'ы для сохранения состояния. Это сейчас на практике популярнее.&lt;br /&gt;
&lt;br /&gt;
== Согласованность и изоляция ==&lt;br /&gt;
В базах данных различают разные уровни изоляции (isolation level), максимальный уровень — сериализуемость (serializability).&lt;br /&gt;
Это когда все транзакции можно упорядочить и получить согласованную историю, как если бы они выполнялись последовательно.&lt;br /&gt;
&lt;br /&gt;
Можно брать блокировку сразу на все узлы, но это не очень эффективно и распределённая блокировка — это сложно, поэтому обычно дают блокировки разным данным в пределах одного узла.&lt;br /&gt;
Чтобы сделать транзакцию, надо взять нужные блокировки (даже на чтение) и отпустить их, но при этом не вляпаться во взаимные блокировки или несогласованность (по-факту то транзакция не мгновенная).&lt;br /&gt;
Для этого используется [[2 Phase Locking|алгоритм двухфазной блокировки]].&lt;br /&gt;
&lt;br /&gt;
Более сложная штука — MVCC (MultiVersion Concurrency Control), это когда мы для каждой транзакции создаём &amp;quot;снимок&amp;quot; базы данных (наверняка при помощи персистентных структур данных)&lt;br /&gt;
и дальше транзакция работает с ним.&lt;br /&gt;
Например, в транзакциях только на чтение это позволяет экономить блокировки.&lt;br /&gt;
А если появились записи, то надо как-то пробовать решать конфликты или даже просто откатывать транзакцию, если данные, которые она читала, уже кем-то были изменены.&lt;br /&gt;
&lt;br /&gt;
== Подтверждение транзакции в распределённой системе ==&lt;br /&gt;
Блокировки у нас локальны и берутся просто, но нам надо, чтобы все участники атомарно пришли к решению завершать транзакцию.&lt;br /&gt;
Можно использовать алгоритмы распределённого консенсуса, но они сложные.&lt;br /&gt;
Классическое решение в базах данных — [[2 Phase Commit|алгоритм двухфазного коммита]] (не имеет никакого отношения к двухфазной блокировке).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71590</id>
		<title>Самостабилизирующиеся алгоритмы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71590"/>
				<updated>2019-06-03T21:00:43Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Поиск остовного дерева */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Самостабилизирующие алгоритмы''' — это идея построения алгоритмов, устойчивых к ошибкам:&lt;br /&gt;
* Код потерять сложно, поэтому мы считаем, что он не портится при падении узлов.&lt;br /&gt;
* Алгоритм может работать с любой комбинацией данных.&lt;br /&gt;
* Из любого состояния мы попадаем в '''легальное''' через конечное число шагов (при отсутствии сбоев).&lt;br /&gt;
}}&lt;br /&gt;
Тогда от ''любого'' сбоя мы через конечное число шагов будем восстанавливаться без консенсусов и прочих развлечений.&lt;br /&gt;
== Взаимное исключение ==&lt;br /&gt;
Dijkstra Stabilizing Token Ring Algorithm.&lt;br /&gt;
&lt;br /&gt;
Сначала надо переформулировать задачу: мы говорим, что каждый процесс в системе может либо '''иметь привилегию''', либо не иметь.&lt;br /&gt;
В произвольном состоянии системы привилегия может быть у произвольного количества процессов, но через конечное число шагов она остаётся только у одного процесса и мы входим в легальное состояние.&lt;br /&gt;
Дальше остаёмся только в легальных состояниях.&lt;br /&gt;
&lt;br /&gt;
TODO: а какие сообщения процессы посылают друг другу? Могут ли быть ошибки (наверное, нет)? Может ли система быть асинхронной (наверное, тоже нет)?&lt;br /&gt;
&lt;br /&gt;
Все $N$ процессов будут замкнуты в кольцо, в котором один процесс назван &amp;quot;первым&amp;quot;.&lt;br /&gt;
У каждого процесса есть состояние — число от 0 до $K-1$, причём $K \ge N$ — параметр алгоритма.&lt;br /&gt;
&lt;br /&gt;
По определению положим, что у процесса есть привилегия, если:&lt;br /&gt;
* Он первый и его значение $S$ совпадает со значением $L$ следующего по часовой стрелке процесса.&lt;br /&gt;
* Он не первый и его $S$ не совпадает с $L$.&lt;br /&gt;
&lt;br /&gt;
Например, на рисунке ниже толстая граница у выделенного процесса, а жёлтым обозначена привилегия:&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-self-stabilization-legal.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Правила перехода в новое состояние:&lt;br /&gt;
* Для первого процесса: если была привилегия ($S=L$), то переходим в состояние $(S + 1) \bmod K$&lt;br /&gt;
* Для не-первого процесса: если привилегия есть ($S \neq L$), то переходим в состояние $&lt;br /&gt;
Пример двух переходов:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-1.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, в легальном состоянии привилегия у нас ходит по кругу, как в алгоритме с токеном.&lt;br /&gt;
Но там потеря токена была смертельной для алгоритма, а у нас — не смертельна.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство стабилизируемости ===&lt;br /&gt;
'''Лемма''': в любом состоянии хотя бы у одного процесса есть привилегия.&lt;br /&gt;
В противном случае у нас, с одной стороны, все значения машин равны друг другу (потому что для каждой машины, кроме первой, её значение совпадает со следующей по кругу), а с другой стороны значение первой машины и её соседа должны отличаться, противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': что бы не происходило в системе, через $O(N^2)$ шагов в системе первый процесс сделает ход.&lt;br /&gt;
'''Доказательство (с лекции)''': если первый процесс не делает ход, то следующий за ним против часовой стрелки процесс 2 сможет сделать максимум один ход: взять себе значение первого процесса.&lt;br /&gt;
Процесс 3 после каждого хода процесса 2 может сделать максимум один ход: взять себе значение процесса 2.&lt;br /&gt;
То есть процесс 3 может сделать не больше двух ходов (один исходно, один после хода процесса 2).&lt;br /&gt;
Аналогично, процесс 4 может сделать не больше трёх ходов, и так далее.&lt;br /&gt;
Итого мы получаем, что если первый процесс не делает шаги, то через $O(N^2)$ шагов привилегия полностью исчезнет, чего не бывает.&lt;br /&gt;
&lt;br /&gt;
'''Альтернативное доказательство (проверено рандомом)''': если первый процесс может сделать ход сразу, то всё доказали. &lt;br /&gt;
Иначе у него нет привилегии.&lt;br /&gt;
Заметим, что если следующий за ним по часовой стрелке процесс 2 либо имеет значение, равное ему, либо отличающееся (тогда он имеет привилегию и сразу делает ход).&lt;br /&gt;
Таким образом, через один ход процессы 1 и 2 имеют одинаковые значения.&lt;br /&gt;
Аналогично, через два хода процессы 1, 2 и 3 имеют одинаковые значения.&lt;br /&gt;
А через $N-1$ шаг все процессы гарантированно имеют одинаковые значения (если первый процесс так и не походил).&lt;br /&gt;
Таким образом, через $N-1$ шаг у первого процесса появляется привилегия и он ходит, $N=O(N^2)$.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': рано или поздно у первого процесса будет уникальное $S$.&lt;br /&gt;
'''Доказательство''': все остальные процессы умеют только копировать состояния друг у друга, а первый процесс ходит бесконечно.&lt;br /&gt;
Поэтому рано или поздно он перейдёт на состояние, которое не совпадает ни с одним из оставшихся $N-1$ состоянием.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': через $O(N^2)$ после этого система стабилизируется.&lt;br /&gt;
'''Альтернативное доказательство (не с лекции)''': это состояние будет сразу же скопировано на второй процесс, потом сразу же скопировано на третий, и так далее, после чего мы прийдём в состояние, где все значения равны, а оно легальное.&lt;br /&gt;
&lt;br /&gt;
== Поиск остовного дерева ==&lt;br /&gt;
Такая задача возникает, например, в internet of things: набросали с вертолёта на поле размером 3км*3км много хрупких устройств со слабыми антеннами, которым надо соединиться в единую сеть. При этом топология связи там неполная и половина устройств подохла.&lt;br /&gt;
А мы хотим построить дерево, чтобы узлы могли друг с другом общаться (а не каждый каждому передавать, потому что тогда надо бороться с циклами).&lt;br /&gt;
&lt;br /&gt;
Решение начинается с инициатора (например, узел, которому надо что-нибудь узнать про всех остальных), которому это дерево нужно.&lt;br /&gt;
&lt;br /&gt;
Каждый узел поддерживает у себя $d$ (расстояние до корня) и $p$ (узел-предок в дереве).&lt;br /&gt;
Корень всегда ставит у себя $d=0$ и $p=-1$, а остальные узлы в постоянном режиме делают:&lt;br /&gt;
* Найти соседа $j$ с минимальным $d_j$&lt;br /&gt;
* Установить его в качестве своего родителя и $d_i=d_j+1$&lt;br /&gt;
&lt;br /&gt;
Тогда корень стабилизируется сразу, узлы, которым корень виден, стабилизируются через одну итерацию, их соседи — через две, и так далее.&lt;br /&gt;
&lt;br /&gt;
Если какой-нибудь узел выпадает, то его дети найдут себе кого-нибудь ещё и снова встроятся в дерево.&lt;br /&gt;
&lt;br /&gt;
Единственная проблема — если умирает корень, но тогда узнавший об этом узел может инициировать перестроение дерева (если у нас цель — связь).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71589</id>
		<title>Самостабилизирующиеся алгоритмы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71589"/>
				<updated>2019-06-03T20:49:28Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Взаимное исключение */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Самостабилизирующие алгоритмы''' — это идея построения алгоритмов, устойчивых к ошибкам:&lt;br /&gt;
* Код потерять сложно, поэтому мы считаем, что он не портится при падении узлов.&lt;br /&gt;
* Алгоритм может работать с любой комбинацией данных.&lt;br /&gt;
* Из любого состояния мы попадаем в '''легальное''' через конечное число шагов (при отсутствии сбоев).&lt;br /&gt;
}}&lt;br /&gt;
Тогда от ''любого'' сбоя мы через конечное число шагов будем восстанавливаться без консенсусов и прочих развлечений.&lt;br /&gt;
== Взаимное исключение ==&lt;br /&gt;
Dijkstra Stabilizing Token Ring Algorithm.&lt;br /&gt;
&lt;br /&gt;
Сначала надо переформулировать задачу: мы говорим, что каждый процесс в системе может либо '''иметь привилегию''', либо не иметь.&lt;br /&gt;
В произвольном состоянии системы привилегия может быть у произвольного количества процессов, но через конечное число шагов она остаётся только у одного процесса и мы входим в легальное состояние.&lt;br /&gt;
Дальше остаёмся только в легальных состояниях.&lt;br /&gt;
&lt;br /&gt;
TODO: а какие сообщения процессы посылают друг другу? Могут ли быть ошибки (наверное, нет)? Может ли система быть асинхронной (наверное, тоже нет)?&lt;br /&gt;
&lt;br /&gt;
Все $N$ процессов будут замкнуты в кольцо, в котором один процесс назван &amp;quot;первым&amp;quot;.&lt;br /&gt;
У каждого процесса есть состояние — число от 0 до $K-1$, причём $K \ge N$ — параметр алгоритма.&lt;br /&gt;
&lt;br /&gt;
По определению положим, что у процесса есть привилегия, если:&lt;br /&gt;
* Он первый и его значение $S$ совпадает со значением $L$ следующего по часовой стрелке процесса.&lt;br /&gt;
* Он не первый и его $S$ не совпадает с $L$.&lt;br /&gt;
&lt;br /&gt;
Например, на рисунке ниже толстая граница у выделенного процесса, а жёлтым обозначена привилегия:&lt;br /&gt;
&lt;br /&gt;
[[Файл:distributed-self-stabilization-legal.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Правила перехода в новое состояние:&lt;br /&gt;
* Для первого процесса: если была привилегия ($S=L$), то переходим в состояние $(S + 1) \bmod K$&lt;br /&gt;
* Для не-первого процесса: если привилегия есть ($S \neq L$), то переходим в состояние $&lt;br /&gt;
Пример двух переходов:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-1.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Distributed-self-stabilization-step-2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, в легальном состоянии привилегия у нас ходит по кругу, как в алгоритме с токеном.&lt;br /&gt;
Но там потеря токена была смертельной для алгоритма, а у нас — не смертельна.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство стабилизируемости ===&lt;br /&gt;
'''Лемма''': в любом состоянии хотя бы у одного процесса есть привилегия.&lt;br /&gt;
В противном случае у нас, с одной стороны, все значения машин равны друг другу (потому что для каждой машины, кроме первой, её значение совпадает со следующей по кругу), а с другой стороны значение первой машины и её соседа должны отличаться, противоречие.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': что бы не происходило в системе, через $O(N^2)$ шагов в системе первый процесс сделает ход.&lt;br /&gt;
'''Доказательство (с лекции)''': если первый процесс не делает ход, то следующий за ним против часовой стрелки процесс 2 сможет сделать максимум один ход: взять себе значение первого процесса.&lt;br /&gt;
Процесс 3 после каждого хода процесса 2 может сделать максимум один ход: взять себе значение процесса 2.&lt;br /&gt;
То есть процесс 3 может сделать не больше двух ходов (один исходно, один после хода процесса 2).&lt;br /&gt;
Аналогично, процесс 4 может сделать не больше трёх ходов, и так далее.&lt;br /&gt;
Итого мы получаем, что если первый процесс не делает шаги, то через $O(N^2)$ шагов привилегия полностью исчезнет, чего не бывает.&lt;br /&gt;
&lt;br /&gt;
'''Альтернативное доказательство (проверено рандомом)''': если первый процесс может сделать ход сразу, то всё доказали. &lt;br /&gt;
Иначе у него нет привилегии.&lt;br /&gt;
Заметим, что если следующий за ним по часовой стрелке процесс 2 либо имеет значение, равное ему, либо отличающееся (тогда он имеет привилегию и сразу делает ход).&lt;br /&gt;
Таким образом, через один ход процессы 1 и 2 имеют одинаковые значения.&lt;br /&gt;
Аналогично, через два хода процессы 1, 2 и 3 имеют одинаковые значения.&lt;br /&gt;
А через $N-1$ шаг все процессы гарантированно имеют одинаковые значения (если первый процесс так и не походил).&lt;br /&gt;
Таким образом, через $N-1$ шаг у первого процесса появляется привилегия и он ходит, $N=O(N^2)$.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': рано или поздно у первого процесса будет уникальное $S$.&lt;br /&gt;
'''Доказательство''': все остальные процессы умеют только копировать состояния друг у друга, а первый процесс ходит бесконечно.&lt;br /&gt;
Поэтому рано или поздно он перейдёт на состояние, которое не совпадает ни с одним из оставшихся $N-1$ состоянием.&lt;br /&gt;
&lt;br /&gt;
'''Лемма''': через $O(N^2)$ после этого система стабилизируется.&lt;br /&gt;
'''Альтернативное доказательство (не с лекции)''': это состояние будет сразу же скопировано на второй процесс, потом сразу же скопировано на третий, и так далее, после чего мы прийдём в состояние, где все значения равны, а оно легальное.&lt;br /&gt;
&lt;br /&gt;
== Поиск остовного дерева ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Distributed-self-stabilization-step-2.png&amp;diff=71588</id>
		<title>Файл:Distributed-self-stabilization-step-2.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Distributed-self-stabilization-step-2.png&amp;diff=71588"/>
				<updated>2019-06-03T20:13:11Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Distributed-self-stabilization-step-1.png&amp;diff=71587</id>
		<title>Файл:Distributed-self-stabilization-step-1.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Distributed-self-stabilization-step-1.png&amp;diff=71587"/>
				<updated>2019-06-03T20:12:45Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Distributed-self-stabilization-legal.png&amp;diff=71586</id>
		<title>Файл:Distributed-self-stabilization-legal.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Distributed-self-stabilization-legal.png&amp;diff=71586"/>
				<updated>2019-06-03T20:09:55Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71583</id>
		<title>Самостабилизирующиеся алгоритмы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71583"/>
				<updated>2019-06-03T19:45:55Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Самостабилизирующие алгоритмы''' — это идея построения алгоритмов, устойчивых к ошибкам:&lt;br /&gt;
* Код потерять сложно, поэтому мы считаем, что он не портится при падении узлов.&lt;br /&gt;
* Алгоритм может работать с любой комбинацией данных.&lt;br /&gt;
* Из любого состояния мы попадаем в '''легальное''' через конечное число шагов (при отсутствии сбоев).&lt;br /&gt;
}}&lt;br /&gt;
Тогда от ''любого'' сбоя мы через конечное число шагов будем восстанавливаться без консенсусов и прочих развлечений.&lt;br /&gt;
== Взаимное исключение ==&lt;br /&gt;
&lt;br /&gt;
== Поиск остовного дерева ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71582</id>
		<title>Самостабилизирующиеся алгоритмы</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B0%D0%BC%D0%BE%D1%81%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B8%D0%B5%D1%81%D1%8F_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B&amp;diff=71582"/>
				<updated>2019-06-03T19:45:28Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: Новая страница: «{{Определение |definition= '''Самостабилизирующие алгоритмы''' — это идея построения алгоритмо…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
'''Самостабилизирующие алгоритмы''' — это идея построения алгоритмов, устойчивых к ошибкам:&lt;br /&gt;
* Код потерять сложно, поэтому мы считаем, что он не портится при падении узлов.&lt;br /&gt;
* Алгоритм может работать с любой комбинацией данных.&lt;br /&gt;
* Из любого состояния мы попадаем в '''легальное''' через конечное число шагов (при отсутствии сбоев).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Взаимное исключение ==&lt;br /&gt;
&lt;br /&gt;
== Поиск остовного дерева ==&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_WCP&amp;diff=71581</id>
		<title>Централизованный алгоритм для WCP</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_WCP&amp;diff=71581"/>
				<updated>2019-06-03T19:43:29Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Часы с прямой зависимостью вместо векторных */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Централизованный алгоритм для WCP''' – алгоритм для поиска наименьшего (проще говоря, самого левого) [[Срез, согласованный срез|согласованного среза]] в котором выполняется [[Слабый конъюнктивный предикат (WCP)|слабый конъюнктивный предикат]].&lt;br /&gt;
Если есть хотя бы один согласованный срез, в котором выполняется слабый конъюнктивный предикат, то такой срез существует и единственен (см. [[слабый конъюнктивный предикат]]).&lt;br /&gt;
&lt;br /&gt;
В централизованном алгоритме используются [[Векторные часы|векторные часы]]. Срез задается набором векторных часов для всех процессов или просто вектором, в котором соответствующая компонента показывает время для соответствующего потока.&lt;br /&gt;
&lt;br /&gt;
Суть алгоритма:&lt;br /&gt;
* Есть один процесс-координатор, ответственный за поиск согласованного среза.&lt;br /&gt;
* Остальные процессы обычные, их задача — проверять свои локальные предикаты.&lt;br /&gt;
* Всякий раз, когда впервые с момента последнего отправленного сообщения локальный предикат становится true, оповещаем об этом координатора, указывая свое векторное время (впервые — чтобы не спамить, состояния процесса между посылками сообщений для системы неотличимы). Векторное время при этом увеличивается.&lt;br /&gt;
** Из этого следует, что если есть наименьший согласованный срез, в котором слабый конъюнктивный предикат верен, то в нём векторные часы всех потоков попарно несравнимы.&lt;br /&gt;
** Более того: если у нас есть срез (необязательно согласованный), в котором все векторные часы всех потоков попарно несравнимы, то он согласован (см. [[Срез, согласованный срез|согласованный срез]]).&lt;br /&gt;
** Таким образом нам достаточно искать наименьший срез из событий, в которых выполняется локальный предикат, а все векторные часы попарно несравнимы.&lt;br /&gt;
* Координатор поддерживает в памяти срез-кандидат и очередь необработанных сообщений от каждого процесса. Инвариант: все срезы, у которых хотя бы одна компонента меньше нашего среза-кандидата, гарантированно не подходят.&lt;br /&gt;
* Координатор хранит вектора среза-кандидата и флажок для каждой его компоненты: красный – это событие не может быть последним для данного процесса в срезе-кандидате (т.е. нет согласованного среда с верным предикатом, в котором в данном процессе в срез взяты события до данного или раньше), зеленый – может.&lt;br /&gt;
* Начальное состояние – все по нулям, красные;&lt;br /&gt;
* Обрабатываем приходящие сообщения только от красных процессов, сообщения от зеленых ставим в очередь.&lt;br /&gt;
** Пришедший от красного процесса вектор гарантированно попадает в срез-кандидат.&lt;br /&gt;
** Сравниваем пришедший вектор попарно с другими процессами. Если новый вектор больше, то делаем меньший процесс красным, потому что новый вектор гарантированно попадает, а тогда после меньшего вектора должно идти что-то ещё (иначе не получим попарно несравнимые события).&lt;br /&gt;
** После обработки сообщения делаем бывший красный процесс зеленым.&lt;br /&gt;
* Если все зеленое, то мы нашли согласованный срез.&lt;br /&gt;
&lt;br /&gt;
Пример с найденным согласованным срезом, тут координатор по очереди сделал зелёными все процессы:&lt;br /&gt;
&lt;br /&gt;
[[Файл:wcp-search-central-good.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример с не найденным согласованным срезом, тут координатор сначала сделал зелёным $P$, потом сделал зелёным $S$, а потом получил мажорирующий их вектор от $Q$ и сделал всех красными, кроме $Q$:&lt;br /&gt;
&lt;br /&gt;
[[Файл:wcp-search-central-bad.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Итого центральному координатору требуется $O(N^2m)$ времени и памяти в сумме ($N$ — количество процессов, $m$ — количество сообщений от одного процесса).&lt;br /&gt;
Всего сообщений на алгоритм — $O(Nm)$.&lt;br /&gt;
&lt;br /&gt;
== Оптимизации ==&lt;br /&gt;
=== Уменьшение количества посылок о выполнении предиката ===&lt;br /&gt;
Если в каком-то процессе выполнялся предикат, а потом он получил сообщение, то не надо ещё раз высылать сообщение координатору.&lt;br /&gt;
Доказательство: если бы было решение, где новое состояние процесса после получения сообщения было границей искомого среза, то мы можем сдвинуть это состояние назад. Предикат всё ещё будет выполняться, а срез менее согласованным не станет, т.к. получения сообщений можно выкидывать безболезненно.&lt;br /&gt;
&lt;br /&gt;
На лекции, впрочем, говорилось, что не надо посылать даже если мы просто получили сообщение и предикат стал выполняться.&lt;br /&gt;
&lt;br /&gt;
=== Часы с прямой зависимостью вместо векторных ===&lt;br /&gt;
Если ''каждый'' процесс участвует в вычислении предиката, то нам хватает [[Часы с прямой зависимостью|часов с прямой зависимостью]] вместо векторных.&lt;br /&gt;
&lt;br /&gt;
Смысл в том, чтобы все процессы, которые хоть как-то влияют на предикат, общались напрямую с координатором.&lt;br /&gt;
&lt;br /&gt;
Доказательство: TODO (на лекции не было).&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_WCP&amp;diff=71580</id>
		<title>Централизованный алгоритм для WCP</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_WCP&amp;diff=71580"/>
				<updated>2019-06-03T19:40:31Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Уменьшение количества посылок о выполнении предиката */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Централизованный алгоритм для WCP''' – алгоритм для поиска наименьшего (проще говоря, самого левого) [[Срез, согласованный срез|согласованного среза]] в котором выполняется [[Слабый конъюнктивный предикат (WCP)|слабый конъюнктивный предикат]].&lt;br /&gt;
Если есть хотя бы один согласованный срез, в котором выполняется слабый конъюнктивный предикат, то такой срез существует и единственен (см. [[слабый конъюнктивный предикат]]).&lt;br /&gt;
&lt;br /&gt;
В централизованном алгоритме используются [[Векторные часы|векторные часы]]. Срез задается набором векторных часов для всех процессов или просто вектором, в котором соответствующая компонента показывает время для соответствующего потока.&lt;br /&gt;
&lt;br /&gt;
Суть алгоритма:&lt;br /&gt;
* Есть один процесс-координатор, ответственный за поиск согласованного среза.&lt;br /&gt;
* Остальные процессы обычные, их задача — проверять свои локальные предикаты.&lt;br /&gt;
* Всякий раз, когда впервые с момента последнего отправленного сообщения локальный предикат становится true, оповещаем об этом координатора, указывая свое векторное время (впервые — чтобы не спамить, состояния процесса между посылками сообщений для системы неотличимы). Векторное время при этом увеличивается.&lt;br /&gt;
** Из этого следует, что если есть наименьший согласованный срез, в котором слабый конъюнктивный предикат верен, то в нём векторные часы всех потоков попарно несравнимы.&lt;br /&gt;
** Более того: если у нас есть срез (необязательно согласованный), в котором все векторные часы всех потоков попарно несравнимы, то он согласован (см. [[Срез, согласованный срез|согласованный срез]]).&lt;br /&gt;
** Таким образом нам достаточно искать наименьший срез из событий, в которых выполняется локальный предикат, а все векторные часы попарно несравнимы.&lt;br /&gt;
* Координатор поддерживает в памяти срез-кандидат и очередь необработанных сообщений от каждого процесса. Инвариант: все срезы, у которых хотя бы одна компонента меньше нашего среза-кандидата, гарантированно не подходят.&lt;br /&gt;
* Координатор хранит вектора среза-кандидата и флажок для каждой его компоненты: красный – это событие не может быть последним для данного процесса в срезе-кандидате (т.е. нет согласованного среда с верным предикатом, в котором в данном процессе в срез взяты события до данного или раньше), зеленый – может.&lt;br /&gt;
* Начальное состояние – все по нулям, красные;&lt;br /&gt;
* Обрабатываем приходящие сообщения только от красных процессов, сообщения от зеленых ставим в очередь.&lt;br /&gt;
** Пришедший от красного процесса вектор гарантированно попадает в срез-кандидат.&lt;br /&gt;
** Сравниваем пришедший вектор попарно с другими процессами. Если новый вектор больше, то делаем меньший процесс красным, потому что новый вектор гарантированно попадает, а тогда после меньшего вектора должно идти что-то ещё (иначе не получим попарно несравнимые события).&lt;br /&gt;
** После обработки сообщения делаем бывший красный процесс зеленым.&lt;br /&gt;
* Если все зеленое, то мы нашли согласованный срез.&lt;br /&gt;
&lt;br /&gt;
Пример с найденным согласованным срезом, тут координатор по очереди сделал зелёными все процессы:&lt;br /&gt;
&lt;br /&gt;
[[Файл:wcp-search-central-good.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример с не найденным согласованным срезом, тут координатор сначала сделал зелёным $P$, потом сделал зелёным $S$, а потом получил мажорирующий их вектор от $Q$ и сделал всех красными, кроме $Q$:&lt;br /&gt;
&lt;br /&gt;
[[Файл:wcp-search-central-bad.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Итого центральному координатору требуется $O(N^2m)$ времени и памяти в сумме ($N$ — количество процессов, $m$ — количество сообщений от одного процесса).&lt;br /&gt;
Всего сообщений на алгоритм — $O(Nm)$.&lt;br /&gt;
&lt;br /&gt;
== Оптимизации ==&lt;br /&gt;
=== Уменьшение количества посылок о выполнении предиката ===&lt;br /&gt;
Если в каком-то процессе выполнялся предикат, а потом он получил сообщение, то не надо ещё раз высылать сообщение координатору.&lt;br /&gt;
Доказательство: если бы было решение, где новое состояние процесса после получения сообщения было границей искомого среза, то мы можем сдвинуть это состояние назад. Предикат всё ещё будет выполняться, а срез менее согласованным не станет, т.к. получения сообщений можно выкидывать безболезненно.&lt;br /&gt;
&lt;br /&gt;
На лекции, впрочем, говорилось, что не надо посылать даже если мы просто получили сообщение и предикат стал выполняться.&lt;br /&gt;
&lt;br /&gt;
=== Часы с прямой зависимостью вместо векторных ===&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_WCP&amp;diff=71579</id>
		<title>Централизованный алгоритм для WCP</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%BB%D1%8F_WCP&amp;diff=71579"/>
				<updated>2019-06-03T19:37:29Z</updated>
		
		<summary type="html">&lt;p&gt;Yeputons: /* Оптимизации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
'''Централизованный алгоритм для WCP''' – алгоритм для поиска наименьшего (проще говоря, самого левого) [[Срез, согласованный срез|согласованного среза]] в котором выполняется [[Слабый конъюнктивный предикат (WCP)|слабый конъюнктивный предикат]].&lt;br /&gt;
Если есть хотя бы один согласованный срез, в котором выполняется слабый конъюнктивный предикат, то такой срез существует и единственен (см. [[слабый конъюнктивный предикат]]).&lt;br /&gt;
&lt;br /&gt;
В централизованном алгоритме используются [[Векторные часы|векторные часы]]. Срез задается набором векторных часов для всех процессов или просто вектором, в котором соответствующая компонента показывает время для соответствующего потока.&lt;br /&gt;
&lt;br /&gt;
Суть алгоритма:&lt;br /&gt;
* Есть один процесс-координатор, ответственный за поиск согласованного среза.&lt;br /&gt;
* Остальные процессы обычные, их задача — проверять свои локальные предикаты.&lt;br /&gt;
* Всякий раз, когда впервые с момента последнего отправленного сообщения локальный предикат становится true, оповещаем об этом координатора, указывая свое векторное время (впервые — чтобы не спамить, состояния процесса между посылками сообщений для системы неотличимы). Векторное время при этом увеличивается.&lt;br /&gt;
** Из этого следует, что если есть наименьший согласованный срез, в котором слабый конъюнктивный предикат верен, то в нём векторные часы всех потоков попарно несравнимы.&lt;br /&gt;
** Более того: если у нас есть срез (необязательно согласованный), в котором все векторные часы всех потоков попарно несравнимы, то он согласован (см. [[Срез, согласованный срез|согласованный срез]]).&lt;br /&gt;
** Таким образом нам достаточно искать наименьший срез из событий, в которых выполняется локальный предикат, а все векторные часы попарно несравнимы.&lt;br /&gt;
* Координатор поддерживает в памяти срез-кандидат и очередь необработанных сообщений от каждого процесса. Инвариант: все срезы, у которых хотя бы одна компонента меньше нашего среза-кандидата, гарантированно не подходят.&lt;br /&gt;
* Координатор хранит вектора среза-кандидата и флажок для каждой его компоненты: красный – это событие не может быть последним для данного процесса в срезе-кандидате (т.е. нет согласованного среда с верным предикатом, в котором в данном процессе в срез взяты события до данного или раньше), зеленый – может.&lt;br /&gt;
* Начальное состояние – все по нулям, красные;&lt;br /&gt;
* Обрабатываем приходящие сообщения только от красных процессов, сообщения от зеленых ставим в очередь.&lt;br /&gt;
** Пришедший от красного процесса вектор гарантированно попадает в срез-кандидат.&lt;br /&gt;
** Сравниваем пришедший вектор попарно с другими процессами. Если новый вектор больше, то делаем меньший процесс красным, потому что новый вектор гарантированно попадает, а тогда после меньшего вектора должно идти что-то ещё (иначе не получим попарно несравнимые события).&lt;br /&gt;
** После обработки сообщения делаем бывший красный процесс зеленым.&lt;br /&gt;
* Если все зеленое, то мы нашли согласованный срез.&lt;br /&gt;
&lt;br /&gt;
Пример с найденным согласованным срезом, тут координатор по очереди сделал зелёными все процессы:&lt;br /&gt;
&lt;br /&gt;
[[Файл:wcp-search-central-good.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример с не найденным согласованным срезом, тут координатор сначала сделал зелёным $P$, потом сделал зелёным $S$, а потом получил мажорирующий их вектор от $Q$ и сделал всех красными, кроме $Q$:&lt;br /&gt;
&lt;br /&gt;
[[Файл:wcp-search-central-bad.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Итого центральному координатору требуется $O(N^2m)$ времени и памяти в сумме ($N$ — количество процессов, $m$ — количество сообщений от одного процесса).&lt;br /&gt;
Всего сообщений на алгоритм — $O(Nm)$.&lt;br /&gt;
&lt;br /&gt;
== Оптимизации ==&lt;br /&gt;
=== Уменьшение количества посылок о выполнении предиката ===&lt;br /&gt;
Если в каком-то процессе выполнялся предикат, а потом он получил сообщение, то не надо ещё раз высылать сообщение координатору.&lt;br /&gt;
Доказательство: если бы было решение, где новое состояние процесса после получения сообщения было границей искомого среза, то мы можем сдвинуть это состояние назад. Предикат всё ещё будет выполняться, а срез менее согласованным не станет, т.к. получения сообщений можно выкидывать безболезненно.&lt;br /&gt;
&lt;br /&gt;
=== Часы с прямой зависимостью вместо векторных ===&lt;/div&gt;</summary>
		<author><name>Yeputons</name></author>	</entry>

	</feed>