Как стать автором
Обновить

Комментарии 60

А вы не могли бы сравнить ваше решение с MongoDB 4.0? Они недавно добавили мульти-документные транзакции.
мы не используем mongodb, поэтому на основании практического опыта — нет. да и про то как работают их транзакции я не нашел статей — только маркетинговые материалы.
но вообще на тему исследований распределенных БД стоит иногда заглядывать на jepsen.io, думаю рано или поздно там появится тест и про 4.0.0.
Еще бы с Neo4j сравнить…
НЛО прилетело и опубликовало эту надпись здесь
Оговорюсь, что это полностью разные системы, сравнивать их (совсем не) корректно. Можем попробовать сравнить разве что как реализован ACID там. Опять же мы не используем neo4j, поэтому мои выводы чисто теоретические и основаны на том, что я только что прочитал в neo4j.com/docs/operations-manual/current/ha-cluster/architecture
Итак:
1. Координатор транзакций и сторадж совмещен. Соотвественно, кратковременные тормоза в подсистеме ввода вывода приводят к тормозам на коммите. В c*one — координатор отделен от стораджа, стораджа составляют отдельный кворум со спекулятивным исполнением, что исключает подобный сценарий.
2. Запись попадает сначала на мастер и потом на все слейвы. Соотвественно если мастер сначала тормознул и потом выключился ( как это обычно и происходит ), то часть изменений будет пропущена, а при возврате такого мастера возникнет «Data branching», который «can be reviewed and the situation be resolved» — как я понимаю вручную. До этого времени, предположу, БД не работает как минимум на запись, а может и на чтение тоже. В c*one такая ситуация невозможна.
3. Выборы взамен отказавшего мастера происходят после обнаружения отказа протоколом raft. про что подробно написано в статье — в c*one выборы не запускаются.
4. Не нашел про партиционирование транзакций ни слова, предположу что мастер глобальный на все транзакции кластера. А как написано «If the master goes down, any running write transaction will be rolled back and new transactions will block or fail until a new master has become available.» означает что до завершения выборов запись данных полностью не работает. В c*one нет единого глобального мастера — их несколько, выборов нет, как уже писал.
5. А вот это намекает на проблемы в масштабировании «All instances in the cluster have full copies of the data in their local database files». Ну или это некорректно сформулировано.

В общем и целом, на основании доки, в neo4j достаточно классический подход к HA, он приблизительно такой же, как и в sql server например.
НЛО прилетело и опубликовало эту надпись здесь

1) А как же ваш тарантул, почему он не подошел?
2) Ваша база опровергает CAP ?

1. почему вы думаете что он бы подошел? что там сделано лучше чем в c*one? что хуже?
2. нет

В тему сравнения с другими решениями.


Вы не смотрели CockroachDB? У них очень хорошо описаны их архитектурные решения. Даже на вскидку из статьи вы упоминали что взяли логические часы Лэмпорта, в том же кокроаче взяли более развитую идею Hybrid Logical Clock ?

Не эксперт по Тарантулу, но, насколько я знаю, три года назад (когда, судя по посту, начинался проект из топика) они только начинали создавать персистентное хранилище Vinyl. Если бы это было год назад, мой первый вопрос тоже был бы — почему не Тарантул.

Точнее Mail.ru Group вы же входите в неё (по поводу ответа, ваш или нет).
Выходит если у вас есть строгая консистентность, значит вы жертвуете доступностью, а иначе CAP для вас не работает.
Я не знаю, подошел бы он вам или нет. Возможно это дороже, так как все в ОЗУ хранится, но работа должна быть быстрее чем твердотельными носителями.
Естественно, если один из координаторов недоступен, то есть период когда невозможна запись транзакций. Тут все в полном соотвествии с CAP. Другое дело, что этот период очень короткий ( за счет отсутсвия выборов и присутсвия спекуляций ) — около 200-300мс, что позволяет повторить транзакцию с клиента при отказе координатора и при этом уложиться в таймаут. Что тоже не противоречит CAP, но на практике приводит к тому, что отказ координатора проходит незамеченным.

В CAP доступность определяется как бинарное св-во, поэтому считается не возможным выполнение таких строгих требований одновременно.


Но на практики, нам достаточно что система доступна 99.9999%, что позволяет системе удовлетворять всем 3-м св-м из теоремы в большую часть времени. На сколько я это понимаю.

Да действительно, под A подразумевают 100% доступность, чего не бывает на практике.
А вы пробовали большее количестве координаторов, укладываетесь в SLA или нет (ведь потребности будут расти)?
Еще вопрос, сколько человек писало проект?
И когда планируется полный переход на вашу базу?
По дизайну нагрузка на координаторов небольшая, растет медленно. Сейчас на самом нагруженном кластере их всего 12, пока с SLA все ок.
Основная разработка велась силами 2 человек — ваш покорный слуга и hristoforov, около 6 месяцев прошло от начала проекта до начала внедрения. Впоследствии, как у нас принято, каждый из разработчиков — кто хотел — смог поучаствовать.
Переход на c*one практически уже совершен, в SQL Server остались всякие некритичные данные — то, что долго и бессмысленно переносить. Вся новая разработка происходит только на c*one.
Спасибо за пост, было приятно прочитать и вспомнить. Но ведь это все уже было на джокере в 2014, даже слайды из того доклада! И гораздо интереснее было бы не просто прочитать еще раз что и как у вас сделано, а узнать что изменилось за эти 4 года. Где получилось даже лучше, чем вы рассчитывали, а где, напротив, что-то пошло совсем не так.
Не все ходят по JUGовским конференциям, части аудитории удобнее прочитать в виде статьи, а в свое время руки не дошли. Однако, что интересно, тема не потеряла актуальность за это время.
По итогам эксплуатации основная идея видно, что рабочая, за это время было множество мелких инцидентов, да и несколько крупных аварий, что позволило обнаружить и пофиксить множество проблем в основном в Cassandra — gossip (очень нехорошо ведет себя в нестабильной сети), repair, streaming, range tombstones, compaction, всего не упомнишь что потрогали или переписали.
Что, с одной стороны, может напугать, но с другой — подтверждает правильность того, что изначально выбирали движок для хранилища который мы знаем и можем сами поддерживать. Ведь проблемы есть абсолютно со всеми СУБД ( про синие экраны SQL Server рассказывал в лицах на Джокере, если помните ) весь вопрос в том кто и как быстро их может диагностировать и исправлять.

В опенсурс не планируете?

Спасибо! Было интересно почитать. Мы ряд проектов успешно перевели с Cassandra на Scylla и получили серьезный прирост производительности на текущих серверах. Вы не изучали возможность перехода на Scylla?
Нет, так как мы не упираемся в скорость CPU — по большей части упоры в сеть, в диски, в подсистему менеджмента памяти linux. А диагностировать проблемы в java приложении значительно легче, чем в C. С этой позиции простой поиск github.com/scylladb/scylla/issues?utf8=✓&q=coredump дает некоторую пищу для размышлений.

Cерьезный прирост — это слишком обще. Интересно было бы узнать подробности что было до перехода на scylla и после? Что за данные? Насколько запросы к ним попадают в кеш? Да и общий профиль нагрузки. Не знаю, насколько это влезет все в коммент — может и на статью потянет ;-)
Нас в первую очередь интересовал уход от Java по ряду причин. В настоящий момент мы готовим отчет по одному из проектов с условиями и результатами нагрузочного тестирования. У разработчика также доступны результаты сравнительных тестов: www.scylladb.com/product/benchmarks
да, эти бенчи я видел, они явно маркетинговые и поэтому неинтересны. буду ждать от вас отчета с нетерпением ;-)
Если у Вас 200 серверов, и выход из строя одного означает, что Ваш сайт недоступен пользователю, то дело не в отказоустойчивости.
Если более внимательно прочитать предложение, к которому вы прицепились, оно начинается со слов «Допустим, у вас сервер» и продолжается «А если у вас 200 серверов». По этому можно предположить, что речь идет о некоем гипотетическом сайте. А цель данного гипотетического предположения в том, чтобы продемонстрировать читателю простую математику сложения отказов при масштабировании системы.

Наш сайт — конечно же доступен при отказе любого из компонентов системы, в том числе и при полном отказе датацентра. Более подробно об этом можно посмотреть например тут: www.youtube.com/watch?v=JZiQKgx2HJM
А цель данного гипотетического предположения в том, чтобы продемонстрировать читателю простую математику сложения отказов при масштабировании системы.


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

Моя цель была объяснить, что 200 серверов хранилища данных выходят из строя по иным причинам, их отказ, когда серверов такое множество, выходят из строя одинаково часто, не зависимо от присутствия службы СУБД, или её отсутствия, и что в принципе, если отказаться от содержания статьи, рассматривать отказы техники, дело интересное, и устройства ПО, которые при этом надо выполнить, ни чем не отличаются, если противопоставить СУБД или не СУБД службы транспортировки и складирования цифровых запасов.

После чего отсутствие СУБД становится бессмысленным и зловредным.
Нам удалось добиться такого времени отклика с использованием сборщика мусора G1, позволяющего указать цель по продолжительности пауз GC. Однако, иногда, достаточно редко, паузы сборщика выходят за рамки 50 мс, что может привести к ложному обнаружению отказа. Чтобы такого не было, координатор не сообщает об отказе удаленной ноды при пропаже первого же heartbeat-сообщения от нее, только если пропало несколько подряд.Так нам удалось добиться обнаружения отказа ноды координатора за 200 мс.

А можно подробностей про машины на которых запускаете, с какими параметрами запускаете, какая версия java и были ли сравнения с другими GC ?

Запускаем на Java8, понятие «машина» сейчас довольно расплывчатое — выделено 8 vcores в one-cloud.
В ключах тоже все более менее стандартно:
-XX:+DisableExplicitGC -XX:+UseG1GC -XX:MaxGCPauseMillis=50 XX:SurvivorRatio=8 XX:MaxTenuringThreshold=3 -XX:MetaspaceSize=256M -XX:-OmitStackTraceInFastThrow -XX:+PerfDisableSharedMem -Xms7g -Xmx7g -XX:+ParallelRefProcEnabled -XX:InitiatingHeapOccupancyPercent=25 -XX:GCPauseIntervalMillis=400

Сравнивали в основном с CMS, есть планы попробовать metronome из OpenJ9, да руки не дошли. По сравнению с CMS, G1 дает лучшую адаптацию к изменению паттернов нагрузки и короче паузы на ГЦ в ситуации наличия значительного запаса по памяти и CPU. Поскольку для координаторов минимальные паузы критичны, то выбрали G1. При этом на нодах-хранилищах работает CMS — там такие большие запасы экономически неоправданны, да и паузы в 150-200ms некритичны благодаря спекуляциям.

Не думали shenandoah погонять или java10 где G1 еще более паралельный? В любом случаи интересно будет ознакомиться с результатми тестирования вами metronome.

шенанду думали, пробовали, но пока далеко не продвинулись — были некоторые проблемы в нем.

интересно будет узнать, как изменится все после перехода на java10
буду признателен если в твиттер отпишитесь или сюда, или в любую другую статью=)

Спасибо за статью. Мне не совсем ясно, что происходит в случае изменения условий поисковых запросов. Создается новый индекс?
сорри, мазанул по кнопкам, ответил ниже
Да, до того как новые запросы могут работать нужно создать под них индекс. Само создание индекса происходит в фоне, на работу клиентов почти не влияет — есть только небольшие флуктуации во временах отработки запросов. На практике самое долгое создание индекса занимало около 10 часов, но там и датасет достаточно большой — фотки, около 20ТБ.

С индексами интересно также то, что в C*one можно выключать/включать чтение из них индивидуально. Таким образом мы можем ставить какие либо эксперименты с ними — например сделать 2 индекса с одинаковым индексным выражением, но разным порядком следования ключей или перестраивать их плавно переводя чтения из старого в новый индекс итп
Я правильно понял, что у клиентов (для запросов вне Tx) указан единственный contact point — локальный Fat Сlient и отключен discovery (через whitelist policy?)?
Не уверен что полностью понял вопрос. Поскольку клиент — это java приложение, поэтому строго говоря никакого contact point у него нет — он сам и есть fat client. Как и обычная нода кассандры он подсоединяется к кластеру и делает gossip exchange с координаторами и хранилищами сам, точно так же как это делают сами ноды Cassandra. Естественно, запускать gossip exchange между самими клиентами бессмысленно и на эту тему мы дописали кода в gossip.
Теперь понятно. Спасибо.
Можете еще немного рассказать о том насколько вырос перфоманс (и в каких кейсах) по сравнению c использованием cassandra driver?
Было очень интересно прочитать, спасибо. Не уверен, что полностью понял часть про скорость работы реализованных индексов, конкретно:

> [..] То есть добавление индексов почти не потребляет ресурсы и практически не влияет на скорость применения модификаций.

При обновлении записи, лок над записью удерживается пока не обновятся ее «копии» во всех индексах? Не могли бы рассказать эту часть подробнее, почему реализованный механизм быстрее тех, что используется в «обычных SQL БД»?
Тут речь идет о «классическом» индексе, основанным в большинстве классических БД на вариантах Б-дерева. Запись в Б-дерево подразумевает предварительное чтение и возможную последующую модификацию нескольких страниц индекса — как минимум на каждом уровне дерева ( для инсерта ) или даже 2 подобных прохода ( для апдейта ). Само по себе подобное чтение означает некоторое количество random reads на диск, что медленно. Кроме того, поскольку в таком классическом индексе обновляются единственные копии этих страниц, для предотвращения их одновременной модификации могут применяться локи на страницы индексов в транзакции, что вызывает дополнительные ожидания локов.
Чем больше ключей в индексе, тем больше глубина дерева, тем больше таких чтений и локов необходимо на изменение каждого ключа -> скорость записи деградирует нелинейно.
Таким образом запись в индекс становится дороже, чем запись в основную таблицу ( если она heap, как в oracle ) или такой же ( если она тоже btree как в SQL Server ).

В c*one ( на самом деле в Cassandra ) для хранения данных исползуется LSM Tree, запись в которую не деградирует при увеличении их количества. Кроме того запись не требует предварительного чтения и применяется сначала в memtable ( т.е. в память ).
Поэтому, c*one для генерации изменения в индекс не нужно его предварительно читать — все изменения всех индексов могут быть сгенерированы на основании данных одной только изменяемой в транзакции записи. При коммите в батч записывается просто несколько дополнительных мутаций для индексов, то есть батч вырастает на несколько десятков байт, что ничтожно, относительно затрат на обработку самого батча. Сами эти затраты тоже будут легче относительно «классической» БД, так как это запись в лог батча и применение мутаций в мемтаблицы соотвествующих реплик, плюс необходимая коммуникация, которая, впрочем, происходит параллельно и асинхронно ( без необходимости что то еще читать с дисков ).
Нет, ведь они начали разрабатываться уже после того как мы рассказали про то, что мы сделали и запустили global indexes, можно почитать issues.apache.org/jira/browse/CASSANDRA-6477 ( вообще даже стоит почитать, чтобы понимать как это работает на самом деле )

С точки зрения реализации, materialized view приносит с собой дополнительную нагрузку при записи: + дополнительное чтение и logged batch на каждый индекс на каждой реплике.
В c*one индекс функционально похож ( местами даже более удобен ), но за счет гарантий согласованности на координаторе его поддержка практически ничего не стоит ( только дополнительная запись, которая в Cassandra значительно дешевле чтения ).

Ну и понятно MV не может быть строго консистентен ( только eventually ) с измененными данными в основной таблице, об этом нужно помнить.
Какой consistency level вы используете для чтения/записи в кассандру?
В c*one — только QUORUM, в хранилищах со слабосогласованными данными — от local read до QUORUM. В редких случаях даже ALL ( но — не для обслуживания клиентских запросов, его для этого использовать ни в коем случае нельзя )
Можете привести пример конфигурации REPLICATION для keyspace'ов, для которых вы всегда используете QUORUM, и которые находятся в разных ДЦ?
в четырех московских дата-центрах, что позволяет обеспечивать сетевую задержку менее 1 мс между ними

Я правильно понял, что тут речь идет о задержке <1мс именно между ДЦ?
ответил ниже
CREATE KEYSPACE guest_history WITH replication = {
'class': 'NetworkTopologyStrategy',
'kc': '1',
'pc': '1',
'dc': '1'
};


да, между ДЦ у нас 0.6-0.7мс пинг, ну и каналы норм толщины, в таких условиях использование глобального кворума не вносит неприемлемую для нас задержку.
А какой протокол взаимодействия между клиентами и c*one? Кассандровский (с расширением для поддержки транзакций) или что-то совсем кастомное?
Да, пока кассандровский, пару Verbs добавили для транзакций. Функции StorageProxy выполняются полностью на клиенте, что снимает часть нагрузки с хранилищ. Частая проблема с сильно нагруженными на чтение кластерами — недостаток cpu на разрешение конфликтов/объединение ответов реплик — в c*one решена тем, что выполняется на клиентах, которых сильно больше, чем хранилищ и координаторов.

Недавно правда для клиентов начали свой протокол делать — в эксплуатации не очень удобно иметь двунаправленные соединения на всх клиентов.
Лучше поздно, чем никода ;-)
Случай занес меня на доклад по этой БД на highload 2018 в Москве. На основании прослушанного ( впрочем, ошибиться можем как я, так и докладчик ), можно насравнивать следующее:

Foundation DB является binary KV хранилищем, то есть структура записи не описывается в БД
Из чего есть следующие следствия:
1. Задачи (де)сериализации ключей и значений переходят на прикладного разработчика. эволюция схемы — неприменимое понятие к FDB, соответсвенно разработка прикладной логики усложняется — нужно или писать (де)сериализаторы с поддержкой версионирования и/или разрабатывать процедуры миграции схемы данных самому. В C*One же, так как она использует кассандру все эти задачи решаются на стороне БД.
2. Индексы тоже неприменимое понятие — поскольку FDB не знает о структуре данных, то и индексы по полю построить не может. Саму задачу индексирования придется решать тоже на уровне прикладной логики ( чему и была посвящена значительная часть доклада ). И если в рамках ACID транзакции относительно просто поддержать индексирования новых данных, то для (пере)индексирования старых придется писать какие то приложения и вряд ли они будут эффективными, так как потребуют транзакций на каждый ключ сущности, а сама логика ( даже и ) параллельного обхода всех данных будет производится на клиенте.
В C*One построение индекса происходит непосредственно на нодах с данными, параллельно и независимо друг от друга без необходимости транзакций в каком то виде за счет наличия часов лэмпорта и встроенного механизма разрешения конфликтов.
3. Невозможность изменения в рамках транзакции какой-то части данных или ключа — придется менять значение или ключ целиком. Это приводит к умножению записи в основную таблицу, все ее «индексы» и коммит лог, что может быть проблемой уже при достаточно средних размерах записи и количестве их изменений.

Ноды с данными являются и координаторами транзакций, о минусах чего уже писал.

Интересно работает распределение данных между нодами кластера. Все данные сортированы по значению ключей, ноды сами выбирают какая область ключей будет храниться на какой из них исходя из текущих данных. Заранее такие области выбрать, очевидно, невозможно из-за возможных перекосов в количестве ключей той или иной области значений. Определив эту область нода переносит на себя недостающие части и удаляет лишние после завершения переносов. Процесс повторяется непрерывно по мере жизни кластера. Звучит ОК, но такую машинерию на практике чрезвычайно сложно реализовать так, чтобы она работала надежно и не ломалась при различных сценариях отказов.

Вот и все, что я смог вынести из доклада Олега Илларионова. большое спасибо ему за доклад и удачи в инновациях!
Спасибо, очень интересная статья!

У меня вопрос
Вы пишите
С внедрением C*One снизились и задержки: в SQL операция записи занимала около 4,5 мс. В C*One — около 1,6 мс. Длительность транзакции в среднем меньше 40 мс, коммит выполняется за 2 мс


Правильно ли я понимаю, что «в среднем» — это AVG от времени выполнения всех транзакций?
Время считается от входа в координатор до выхода сообщения о комите на координаторе или на клиенте?

Верно ли, что коммит выполняется за 2 милисекунды – время от отправки batch-запроса в Cassandra от получения ОК от неё?

Если да, то этот ОК кссандра отправляет после успешной реальной физической записи на диск какого количества копий?

И ещё вопрос — диски в кассандре SSD, крутящиеся или какая-то смесь?

Заранее спасибо за ответы и ещё раз спасибо за подробный пост с картинками!

Правильно ли я понимаю, что «в среднем» — это AVG от времени выполнения всех транзакций?
Время считается от входа в координатор до выхода сообщения о комите на координаторе или на клиенте?


Здесь сравнивалось среднее время задержки выполнения методов DAO один с реализацией хранения данных в SQL против другого с реализацией в c*one. Методы семантически повторяют друг друга 1 в 1. Задержки измерялись на клиенте.

Верно ли, что коммит выполняется за 2 милисекунды – время от отправки batch-запроса в Cassandra от получения ОК от неё?


Это время от момента запроса на коммит с клиента до момента подтверждения его от координатора. Соответственно время включает в себя коммуникацию с координатором, время формирования и отправки батча в кассандру, применения кассандрой батча, удаление батча, ну и всевозможные acks.

Если да, то этот ОК кссандра отправляет после успешной реальной физической записи на диск какого количества копий?


В Cassandra, в отличии от классических СУБД физические копии на диск не пишутся для каждой мутации. Записи применяются в memtables и записываются в коммит лог ( более подробно тут )
Вместо этого используется кворум нод — запись считается успешной, если ее прием подтвердили 2 из 3 нод. Потеря такой записи в этом случае вероятна только если единовременно откажут 2 реплики. Поэтому важно эти реплики располагать так, чтобы такого не происходило — например мы располагаем их в разных датацентрах.

И ещё вопрос — диски в кассандре SSD, крутящиеся или какая-то смесь?

Смесь. Для хранения сстаблиц используется SSD, для коммит логов и архивов — HDD.

Архивы — другая интересная деталь позволяет нам не бакапить данные с хранилищ. В сочетании со ежедневными снапшотами и архиворованием коммит логов они позволяют нам восстановить состояние данных на любой момент за последние 30 дней. И этот процесс достаточно быстрый — старая копия данных поднимается за 15-30 минут, что очень быстро для 36ТБ датасета. Этой фичей мы уже пользовались несколько раз при расследовании различного рода инцидентов связанных с пропажей данных.

длительность же всей транзакции ( та, которая 40мс ) — измеряется на координаторе от момента получения команды start от клиента до момента получение commit от клиента.
Спасибо за статью, уточните пожалуйста пару моментов:
Допустим, клиент прислал координатору запрос на открытие транзакции для такой-то сущности с таким-то первичным ключом. Координатор эту сущность блокирует и помещает в таблицу блокировок в памяти.

Блокирует на запись только, т.е. остальные клиенты могут читать?

Таким образом, клиент может прочитать собственные изменения, а другие клиенты эти изменения не видят, потому что хранятся они только в памяти координатора, в нодах Cassandra их еще нет.

А если ваш клиент в это время делает синхронный запрос в другой ваш сервис, которому надо получить из хранилища данные, актуальные относительно текущей транзакции?

И последний: R + W > N? на сколько нод пишете и со скольки читаете?
Блокирует на запись только, т.е. остальные клиенты могут читать?

Читать может, если не находится в контексте текущей транзакции. В противном случае ждет освобождения блокировки.

А если ваш клиент в это время делает синхронный запрос в другой ваш сервис, которому надо получить из хранилища данные, актуальные относительно текущей транзакции?

Естественно, запросы в другой сервис не рекомендуется делать в пределах транзакции, но за всем не уследишь. У транзакции c*one есть таймаут неактивности, сейчас он около 3 секунд, соотвественно если клиент сделал синхронный запрос в какой то другой сервис, и подвис, то через 3 секунды все блокировки автоматически снимаются и такая транзакция откатывается. Такой таймаут — еще одна фича, которой сильно не хватало в SQL Server — при отказе клиента его соединения часто провисали на долгое время, удерживая локи в транзакции и вызывая отказы нормально функционирующих клиентов.

И последний: R + W > N? на сколько нод пишете и со скольки читаете?

У нас 3 ДЦ, должны выдерживать отказ 1 из них, соотвественно 2 + 2 > 3
У нас 3 ДЦ, должны выдерживать отказ 1 из них, соотвественно 2 + 2 > 3


Спасибо, а внутри ДЦ?
Одна реплика. Поскольку связь между ДЦ хорошая, нет смысла делать дополнительные реплики.
Интересная статья, спасибо. Вопрос:

Блокируем альбом по ключу.
Создаем запись в таблице фотографий.
Если у фотографии публичный статус, то накручиваем в альбоме счетчик публичных фотографий, обновляем запись и коммитим транзакцию.


А не рассматривали возможность применить подход Event Soursing?

Т.е. есть некая очередь, допустим, в Kafka.

— При добавлении фотографии туда кладется событие «PhotoAdded»
— Очередь разбирается процессами, в данном случае нам нужен процесс «Album»
— У каждого процесса своя позиция в очереди
— Если нужно отмодерировать фотографию, в очередь кладется «PhotoModerated»
— Процесс «Album» должен понимать события «PhotoAdded» и «PhotoModerated»
— Процесс «Album» может быть запущен в нескольких экземплярах, каждый альбом всегда обрабатывается только один процессом (обеспечивается Kafka)

Конкурентное модифицирование отсутствует, транзакции не нужны.
Привет, Олег.

Две копейки на счет RAFT. А вот твой коврумный протокол, он разве не больше генерируется сообщений чем RAFT в стейбл состоянии? Насколько я помню, когда выборы случились, хертбиты нужны только между лидером и фолловерами.
А у тебя между всеми нодами, если я правильно понял.
Имея RAFT можно также реализовать твой алгоритм. Например поверх ETCD (у которого внутри RAFT), я делал похожий алгоритм выбора лидера. ETCD обеспечивал atomic changes состояния (список нод), в лидером выбиралась нода с меньшам mod_revision. Liveness через leases.

Сорри за орф. ошибки, писал с телефона.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий