Здравствуйте, Cyberax, Вы писали:
C>А как потребуется делать GUI, писать серверы с распределенными транзакциями между разными источниками данных, использовать надежный messaging — тут Эрлангу сразу станет далеко не так все хорошо.
Что касается GUI — это некритично (написать его на PyGTK или GTK/С++ мне было бы даже проще). Хотелось бы узнать Ваше мнение по поводу первоначальной задачи, которая в очень упрощенной форме звучала так: "существует ли принципиальная возможность в 10-20 строчках кода организовать расширяемый кластер с полным сохранением внутреннего состояния в случае сбоя N-1 компьютеров" и "требуется хранить 3 последних результата GetServerValue()". Т.е. мы пишем программу для обработки данных у которой есть внутреннее состояние, и его надо синхронизировать между всеми на случай выключения узла. Один из советов был хранить все в mnesia, но, как я понял из Выших сообщений про "brain-split", это нельзя назвать надежным механизмом, и никаких других более-менее стандартных средств тоже нет? Казалось бы не очень сложная задача для "language designed to support robust, reliable, distributed near real-time applications".
Здравствуйте, mnf, Вы писали:
C>>А как потребуется делать GUI, писать серверы с распределенными транзакциями между разными источниками данных, использовать надежный messaging — тут Эрлангу сразу станет далеко не так все хорошо. mnf>Что касается GUI — это некритично (написать его на PyGTK или GTK/С++ мне было бы даже проще). Хотелось бы узнать Ваше мнение по поводу первоначальной задачи, которая в очень упрощенной форме звучала так: "существует ли принципиальная возможность в 10-20 строчках кода организовать расширяемый кластер с полным сохранением внутреннего состояния в случае сбоя N-1 компьютеров" и "требуется хранить 3 последних результата GetServerValue()".
Я такое могу на Java сделать Смотрим: http://www.terracotta.org/
Тут главное, на самом деле, иметь кластерное хранилище. Попробуй сделать расширяемый кластер и прочее бла-бла на Erlang без Mnesia или MySQL в качетсве хранилища.
Сам по себе Erlang с системами супервизоров и передачи сообщений имеет некоторые примитивы для распределенных систем, но не все.
mnf>Т.е. мы пишем программу для обработки данных у которой есть внутреннее состояние, и его надо синхронизировать между всеми на случай выключения узла. Один из советов был хранить все в mnesia, но, как я понял из Выших сообщений про "brain-split", это нельзя назвать надежным механизмом, и никаких других более-менее стандартных средств тоже нет? Казалось бы не очень сложная задача для "language designed to support robust, reliable, distributed near real-time applications".
Brain-split можно достаточно надежно избежать с помощью избыточной связности. Оно более важно, если у нас есть географически отделенные датацентры (у нас есть).
do_call(Tag, C) ->
Fun = the_func(C),
F = fun() ->
case mnesia:read({reply, Tag}) of
[] ->
%% no cached value
Val = Fun(),
mnesia:write(#reply{tag=Tag,val=Val}),
Val;
[C] ->
%% yes - return cached value
C#reply.val
end
end,
mnesia:transaction(F).
Представим, что у нас во время исполнения функции клиент теряет соединение с сервером, и делает failover на второй сервер. Тогда второй сервер тоже начнет исполнять эту функцию (так как в Mnesia еще не лежит результат выполнения), а потом оба сервера могут спокойно положить результат в Mnesia.
Написал об этом Армстронгу, посмотрим что ответит.
Здравствуйте, Cyberax, Вы писали:
[cut] C>Написал об этом Армстронгу, посмотрим что ответит.
Лучшеб в мейллист, но будем надеяться, что отпишешь о результатах
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, Gaperton, Вы писали:
G>>Интересно, как в этом случае ведет себя мнезия — ведь это она выполняет репликацию. Я думаю, на самом деле все будет в порядке. Но правда любопытно. C>Я не использовал Мнезию для серьезной работы, так что не смотрел туда особо внимательно.
C>Сейчас попробовал найти в доке — похоже, что никак не обрабатывает:
Зато она обнаруживает эту ситуацию. И генерит перехватываемый event. Уже не мало. А далее все должно быть просто — например, тебе надо выбрать главный репозиторий и грохнуть второй.
C>>>Для решения этой проблемы можно использовать такие методы: C>>> Кворумный диск — сервер может работать, только если у него есть доступ к этому диску. Добавляет single-point-of-failure, но на практике достаточно надежно. G>>Ну, дисков они не разделяют. Мнезия реплицирует таблицы через эрланговские сообщения — двухфазным или трехфазным коммитом. G>>Вообще, в эрланге этому подходу соответствует супервижн три, достаточно грамотно его построить, ничего другого не нужно. C>Кворумный диск (точнее, вообще любой кворумный ресурс) используется и если нет разделения дисков, он просто позволяет гарантировать, что система находится в consistent state.
В эрланге для этого диск не нужен. Там процессные линки двунаправленные, поэтому роль кворумного ресурса играет процесс-супервизор. Подчиненный процесс узнает о том, что он отвалился от дерева. Причем, никто не мешает тебе добавить в систему произвольное количество кворумных процессов — пустышек — это совсем элементарно делается. Просто следишь, когда порвется линк, и все. Кроме этого, можно запускать heartbeat.
C>>> Работать только если у нас есть связь с более чем 50% узлов в кластере (для этого нужно минимум три узла). G>>Узлы кластера можно увязать в супервижн три, и держать резервного супервизора — тогда все просто и понятно — мы трактуем недоступный узел как отвалившийся. Думаю, так будет нормально. Опять же, интересно, как такие проблемы решает мнезия. C>Насколько я понимаю, supervisor tree не решает эту проблему — просто сдвигает ее со стороны worker nodes на сторону супервизоров. То есть, если у нас отказывает корневой супервизор, то нам надо решить кому стать следующим корнем. И там все те же самые проблемы.
Отчего же. Супервизор может понять, кто из детей отвалился. Подчиненный процесс понимает, что его от супервизора отрубили, и он спокойно сворачивает активность. Если грохнулся корневой супервизор, то падает все, и система его перезапускает. Когда ты проектируешь отказоустойчивую систему, ты все равно должен выделить trusted код, который падать не должен, и он должен быть очень простым и хорошо отлаженным. А также — код, который ненадежен, в котором ты "толерэйтишь" ошибки. Вот, супервизор и есть такой trusted код, в нем нет ошибок.
Для пущей надежности можно завести резервное supervision tree. Или еще что-нибудь придумать. Причем, на Эрланге такое написать вполне реально и самому — можно произвольную схему реализовать, кода будет порядка нескольких килобайт, не больше десятка. Делов-то.
C>Кстати, мы вообще смотрели как проще делать реплицируемую базу. В итоге, остановились на кластерной файловой системе OCFS2 с избыточной связностью хостов. Там сценарий со split-brain возможен, но для этого требуются очень нереальные условия (падение сразу нескольких интерфейсов на разных хостах, причем одновременно).
Здравствуйте, Gaperton, Вы писали:
C>>Сейчас попробовал найти в доке — похоже, что никак не обрабатывает: G>Зато она обнаруживает эту ситуацию. И генерит перехватываемый event. Уже не мало. А далее все должно быть просто — например, тебе надо выбрать главный репозиторий и грохнуть второй.
Ага, и потерять свои изменения в локальной копии. Насколько я понял, оно обнаруживает partitioned event только после переподключения к другим нодам.
G>Отчего же. Супервизор может понять, кто из детей отвалился. Подчиненный процесс понимает, что его от супервизора отрубили, и он спокойно сворачивает активность. Если грохнулся корневой супервизор, то падает все, и система его перезапускает. Когда ты проектируешь отказоустойчивую систему, ты все равно должен выделить trusted код, который падать не должен, и он должен быть очень простым и хорошо отлаженным. А также — код, который ненадежен, в котором ты "толерэйтишь" ошибки. Вот, супервизор и есть такой trusted код, в нем нет ошибок.
Проблема в том, что один корень — это плохо в любом случае. Нужно иметь хотя бы один hot spare на другой машине. Но тогда возникнет проблема — если теряем связь между hot spare и основным сервером, то получаем все ту же проблему. Hot spare нужно решить, может ли он перехватить управление.
G>Для пущей надежности можно завести резервное supervision tree. Или еще что-нибудь придумать. Причем, на Эрланге такое написать вполне реально и самому — можно произвольную схему реализовать, кода будет порядка нескольких килобайт, не больше десятка. Делов-то.
Можно, но похоже с Mnesia могут быть проблемы.
C>>Кстати, мы вообще смотрели как проще делать реплицируемую базу. В итоге, остановились на кластерной файловой системе OCFS2 с избыточной связностью хостов. Там сценарий со split-brain возможен, но для этого требуются очень нереальные условия (падение сразу нескольких интерфейсов на разных хостах, причем одновременно). G>Интересно, надо будет посмотреть.
Ага. Мы посчитали — нам требуется одновременно (в течение примерно одной секунды) отключить 22 кабеля, чтобы разбить кластер на два partition'а.