multinode autoincrement

61 views
Skip to first unread message

Aleksey Kluchnikov

unread,
Nov 28, 2018, 7:41:14 AM11/28/18
to erlang-russian
Всем привет.
Вопрос вероятно оффтопик, но интересно кто как делает подобное.
Есть кучка нод, все они нуждаются в общем автоинкрементальном счетчике. Как это сделать максимально просто и надежно? Может какая то встроеная фича есть в эрлаге?

Сейчас я использую для этого инстанс redis который всем доступен, но как то хочется он него избавиться как от лишней сущьности.

Danil A. Zagoskin

unread,
Nov 28, 2018, 8:19:17 AM11/28/18
to erlang-...@googlegroups.com
Привет!

Разобью твою задачу на две:
* Консистентность — в терминах эрланга это или единственный процесс на кластер, или единая структура данных на кластер
* Атомарность — скорее всего, это строгая сериализация запросов
* Восстановление на холодном старте (хз, нужно ли в твоей задаче)

Консистентность можно обеспечить глобальным реестром (но модуль global иногда некрасиво залипает на восстановлении кластера),
можно консенсусом типа gen_leader (под ним можно запускать процессы, готовые подхватить роль авторитетного счетчика),
можно взять мнезию (со всеми ее фокусами при восстановлении кластера),
можно посмотреть что-то в сторону CRDT.
Разные подходы будут иметь разную сложность реализации, разное поведение, разные тайминги.

Атомарность тоже зависит от выбранного метода. В случае с процессом это gen_server:call

Восстановление, если нужно, возможно, сильно замедлит отклик всей системы, если сбрасывать каждый хит на диск нескольких нод.

--
Вы получили это сообщение, поскольку подписаны на группу "Erlang по-русски".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес erlang-russia...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес erlang-...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Grigory Fateyev

unread,
Nov 28, 2018, 9:16:46 AM11/28/18
to erlang-...@googlegroups.com
Можно посмотреть в сторону Riak CRDT, но из-за единственного глобального счётчика игра не стоит свеч.

ср, 28 нояб. 2018 г. в 16:19, Danil A. Zagoskin <da...@st-olen.ru>:

Dmitry Belyaev

unread,
Nov 28, 2018, 9:35:34 AM11/28/18
to erlang-...@googlegroups.com, Grigory Fateyev
Можно почитать про distributed consensus: paxos, raft. И можно поискать библиотеки их реализующие, точно видел несколько реализаций на эрланге.
--
Kind regards,
Dmitry Belyaev

Maxim Molchanov

unread,
Nov 30, 2018, 5:14:17 PM11/30/18
to Erlang по-русски
Raft решит эту задачу надежно и без особых плясок. Есть неплохая реализация https://github.com/rabbitmq/ra, API уже стабилизировали, допиливают мелочи, документации для старта хватает.

среда, 28 ноября 2018 г., 15:41:14 UTC+3 пользователь Aleksey Kluchnikov написал:

Aleksey Kluchnikov

unread,
Dec 10, 2018, 2:39:35 AM12/10/18
to erlang-russian
Итого что получилось.
Для rabbitmq/ra нужен 20й otp, а у меня все на 19м поэтому отгреб немаленький рефакторинг. Но это к лучшему, все равно когдато надо.
Ra конечно хорошо, но это что то сложное и похоже он не сохраняет свой стейт на диск, тоесть при  перезагрузке кластера все теряется. Надо все равно при каждом обращении к нему складывать стейт в базу.
Тогда не понятно зачем он нужен если можно сразу в базе хранить инкремент.
Получается что технология ради технологии, или просто не допилили еще.

Думаю реализовать такую схему, без рафта, заодно поробовать новую базу.
Cockroachdb. поднять ее на каждом серваке и сохранить в ней инкремент, только выдавать не по 1, а по диапазону, например по 1000, а дальше нода локально инкрементирует в этом диапазане, как диапазон заканчивается, запрашивать новый. В результате это будет не напряжно для базы. И вроде как консистентно средствами базы.


сб, 1 дек. 2018 г. в 02:14, Maxim Molchanov <mr.e...@gmail.com>:
--

Maxim Molchanov

unread,
Dec 10, 2018, 2:59:09 AM12/10/18
to Erlang по-русски
Насчет ra и хранения стэйта. Стэйт raft протокола сохраняется на диск. За это отвечает  data_dir (https://github.com/rabbitmq/ra/blob/master/src/ra.app.src#L17) 
За реализацию ra_machine и хранение данных отвечает разработчик конечного решения. В примерах действительно реализован простейший случай, fsm сохраняет стэйт в памяти. Но никто не запрещает сохранить его на диск, например используя leveldb, rocksdb или обычные файлики. https://github.com/rabbitmq/ra/blob/master/docs/internals/STATE_MACHINE_TUTORIAL.md в этом примере в apply методы добавляем работу с хранилищем вместо maps и получаем требуемый уровень хранения.

понедельник, 10 декабря 2018 г., 10:39:35 UTC+3 пользователь Aleksey Kluchnikov написал:

Dmitry Belyaev

unread,
Dec 10, 2018, 5:29:30 AM12/10/18
to Aleksey Kluchnikov, erlang-russian
Это состояние, получаемое через рафт, оно не требует дистрибуции, может быть сохранено на локальный диск или в локальную embedded базу данных. В этом и есть преимущество - вместо центральной базы данных распределенной на отдельных нодах, получаешь локальную базу данных на нодах приложения.
Reply all
Reply to author
Forward
0 new messages