LINUX.ORG.RU

Лучшая СУБД для CQRS+Event Sourcing.

 , ,


3

7

Добрый день, мои дорогие любители архитектуры распределенных систем.

Сразу накидаю ссылочек, кто хочет интересное чтиво.

http://martinfowler.com/bliki/CQRS.html

http://habrahabr.ru/post/146429/

http://habrahabr.ru/post/149464/

http://blog.jonathanoliver.com/2011/05/why-i-still-love-cqrs-and-messaging-an...

http://msdn.microsoft.com/en-us/library/jj554200.aspx

Вкратце. CQRS - более общий вариант CRUD, мы не обязательно в DAO записываем те же обЪекты что и читаем (Entities). Вместо этого отправляем асинхронные Command и через время, когда он раздуплится, можем делать Query. Тоесть вместо одного DAO у нас Read Model и Write Model.

Event Sourcing, Write Model. У нас нет сущностей, есть Aggregate, которые реально не сохранены в базе, но определяются общим ID. Так вот, когда мы получаем Command на определенный ID, то мы достаем предыдущие Command на этот ID, реплеим их в памяти, они имеют доступ к общему обьекту Aggregate, который конструируется с нуля поглощая эти Command. Потом мы добавляем к нему новый Command и сохраняем его в базу.

Добавление последнего Command порождает много Event, которые разлетаются к чертям асинхронно во все стороны и там какие-то куски кода сферически в вакууме обновляют Read Model. Например в реальном времени обновляют таблицы, делают real time MapReduce, обновляют карту мира, пишут письма, пофиг.

Read Model может быть бесконечно разнообразным и его можно стереть, перепрограммировать и воспроизвести заново все Event. Их можно добавлять потом и делать сколько угодно штук. Они могут быть даже не в вашей компании. С письмами повторную отправку иногда нужно отключать.

А теперь вопрос. Какая СУБД, желательно из бесконечно масштабируемых, для такого подходит.

Mongo, РСУБД прямо утыканы single point of failure, так что отбросим пока.

Cassandra. Идеально, неубиенная, линейно масштабируется, no single point of failure. Первый ключ (parition/row key) - command id. Второй, поддающийся сортировке - timestamp. Но все омрачает один факт. Не смотря на рекламу что с помощью R+W>N можно достичь strong consistency, это простите брехня. Потому что нет rollback, и потом вылазят проблемы что если write неуспешен, то некоторые чтения могут все же увидеть новые данные. А следующее чтение - старые. А потом опять новые. Нужно просто правильные узлы выбирать. Для вебни - самое то. Но когда CQRS+Event Sourcing система будет наивно колбасить миллион комманд в автоматическом режиме, то может неслабо бабахнуть.

Riak - то же самое вроде, не? Очень хотел бы послушать.

HBase? Очень мало знаю о этой СУБД.

Короче нужна кассандра с роллбеком

★★★★★

Последнее исправление: vertexua (всего исправлений: 6)

Кстати, может в riak какой-то two phase коммит замутить и потом разруливать по vector clock?

В кассандре они за тебя подшумок сами выбирают старшего по timestamp

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 1)

Разве этот паттерн требует определённую СУБД ?

Не смотря на рекламу что с помощью R+W>N можно достичь strong consistency, это простите брехня

Естественно из теоремы кассандра только для AP, без C, а это маркетинговый ход.

anonymous
()
Ответ на: комментарий от anonymous

Разве этот паттерн требует определённую СУБД ?

Хочется подобрать подходящую. Системы с eventual consistency не очень хорошо могут подойти для event store. Если без костылей. Пытаюсь придумать костыли.

Обычные РСУБД или MongoDB каждый слабак может, но для начала лучше подумать как сделать на системах без single point of failure. Если чего, да, попробую их

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 1)

Какая СУБД, желательно из бесконечно масштабируемых, для такого подходит.

РСУБД прямо утыканы single point of failure, так что отбросим пока.

Относительно пофиг, т.к. всё равно придётя писать сервис фронт-енд, который будет обрабатывать входяшие транзакции от клиентов и рассылать эвенты. Он в любом случае будет единой точкой отказа если специально не заморочиться. А если заморочиться, то не будет сильно сложнее сделать из него анаолг ~ replicated state machine. Нужно примерно два разных вида хранилищ, не распределённых:

1. под логи с операциями append, sequence read начиная с какого-то заданного момента и фоновый процесс GC (удаление старых логов). Это можно хоть самому написать, хранилище простое. Оно же будет хранить HEAD.

2. хранилище снапшотов состояний агрегаторов. Это зпись по ключу и чтение по нему же. Т.е. практически любая k/v СУБД.

Консистентность нужна только от баз с логами, тут нужно будет заморочиться с 2PC или с paxos для записи во все реплики. А снапшоты можно просто сбрасывать без особых заморочек т.к. всё равно с какой корректно сохранённой версии накатываться.

mashina ★★★★★
()
Ответ на: комментарий от vertexua

MongoDB каждый слабак может

я бы так не сказал, в этом говне попробуй разобраться.

- тоже подумаю.

anonymous
()
Ответ на: комментарий от mashina

Консистентность нужна только от баз с логами, тут нужно будет заморочиться с 2PC или с paxos для записи во все реплики

Как раз и обсуждаю event store.

2PC

How? Например на базе кассандры, которая лучше всего подходит со своей column family моделью.

paxos

Тут без поддержки базы не представляю как. Самое обидное что в Cassandra 2.0 они кажется реализовали paxos внутри, но для lightweight transactions, которые если я не ошибаюсь стадают от тех же проблем. Не ясно кто их так назвал, ведь в принципе это просто Compare And Swap, который так же отваливается. Я до конца еще не разобрался с тем как они работают. А вы как это понимаете?

vertexua ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Я просто образно выразился )

vertexua ★★★★★
() автор топика
Ответ на: комментарий от vertexua

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

Для лога лучше всего подходит только лог. Фича «column family» иррелевантна для задачи эффективного храненяи лога.

Тут без поддержки базы не представляю как.

Можно посмотреть готовые реализации и сделать как у них или прямо их заюзать. Сходу вспоминается raft

mashina ★★★★★
()
Ответ на: комментарий от mashina

Для лога лучше всего подходит только лог. Фича «column family» иррелевантна для задачи эффективного храненяи лога.

Но ведь я думал не о одной очереди. Я предполагал что система сможет обрабатывать множество event одновременно с консистентностью на уровне агрегата. А между агрегатами пусть хоть синим пламенем горит. И вот тут как раз подошел бы как нельзя кстати вот такой CQL запрос

select * from event_log where aggregate_id=? order by ts

Идеально ложится на DynamoDB/Cassandra. Поверх файла сложновато. Но да, файл подошел бы для одной очереди

Кстати DynamoDB вроде отлично подходит, но пока что не рассматриваем ибо только в амазоне

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 2)
Ответ на: комментарий от disarmer

NET

MS просто отличился парочкой хороших публикаций. На .NET не пишу

Ничуть не реалтайм

Я так и подумал. Хадуп, чо

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 2)
Ответ на: комментарий от vertexua

Идеально ложится на DynamoDB/Cassandra.

Что идеального? Вроде такой запрос ложиться одинаково на любую БД с индексом по ts. Только они обычно хреново себя ведут на последовательном чтении небольшого куска по индексу если вдруг в кеш не попадут.

Но да, файл подошел бы для одной очереди

В файл(ы) можно писать много очередей, если метить их тегами. В общем, это не проблема.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Идеальность в том, что первый ключ - partition key со случайным размещением, а второй - локальный range индекс. А вы предлагаете глобальную сортировку. Можете представить себе распределение нагрузки по узлам с течением времени?

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

А вы предлагаете глобальную сортировку. Можете представить себе распределение нагрузки по узлам с течением времени?

Это будет зависить от роста кол-ва очередй во времени. Никто не мешает шардить очереди по группам log хранилищ. Проблема будет только если заранее нельзя ограничить кол-во очередей и иногда нужно будет делать реконфигурацию кластера (~ добавлять новые log хранилища и ребалансировать распределение). Тога это тоже придётся делать самому, что не очень просто.

mashina ★★★★★
()

Вообще многие говорят о CQRS как о паттерне проектирования. На мой взгляд он слишком сильно влияет на общую архитектуру приложения, что бы называться просто “паттерном проектирования”, поэтому я предпочитаю называть его принципом или подходом. Использование CQRS проникает почти во все уголки приложения.

блин почему он говорит как будто продаёт мне кирби или гербалайф?
я ни слово не понял, звучит очень пафосно и умно, но дальше читать не могу, сейчас уже предложат отдать квартиру и уйти в секту.
неужели нет статей на русском языке? я хочу расширить кругозор.

system-root ★★★★★
()
Ответ на: комментарий от system-root

Просто это хипстерство модно, как nosql и mapreduce. Суть такова: в одну базу складывают для хранения и экспортируют в другую в денормализованном виде. Зачем? Я тоже до сих пор не понял

disarmer ★★★
()
Ответ на: комментарий от mashina

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

Array
()
Ответ на: комментарий от Array

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

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от eternity

Вроде монги и околомонги пока исключаем

vertexua ★★★★★
() автор топика

Допустим, у нас есть кассандра БЕЗ роллбэка. Какими костылями можно подпереть случай с неуспешным write'ом?

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

Допустим, у нас есть кассандра БЕЗ роллбэка. Какими костылями можно подпереть случай с неуспешным write'ом?

Делать retry пока не получится

maxcom ★★★★★
()
Ответ на: комментарий от maxcom

А если пока retry в ДЦ выключат свет, то что? Сразу повдоль?

+ Есть какой-нибудь опробованный фреймворк для CQRS+ES на жабе? В который можно было бы впихнуть свою БД. (кложура тоже интересно)

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

Вот-вот, думаю... Записывать то туда разное можно. Причем с разными уровнями косистентности. Я вот думал еще использовать параллельно статус транзакций в R=W=N=1. Но пока ничего умного не придумал.

Больше всего мешает автоматическое разруливание по старшему timestamp. Были бы людьми, добавили режим когда присылают все разные варианты, их части или сигнатуры.

vertexua ★★★★★
() автор топика
Ответ на: комментарий от maxcom

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

Я тоже думал о варианте чтобы никто таки ничего не почитал, подход с другой стороны.

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

Больше всего мешает автоматическое разруливание по старшему timestamp. Были бы людьми, добавили режим когда присылают все разные варианты, их части или сигнатуры.

Voldemort и Riak так могут

maxcom ★★★★★
()
Ответ на: комментарий от stevejobs

Тактическое отступление. Решил забить делать это на уровне кассандры, пока пишу в тупую и надеюсь на хороший сценарий. Вместо этого выстраиваю инфраструктуру идемпотентных сообщений в Kafka чтобы при фейле можно было ошибаться и начинать с неправильного места в порядке сообщений

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

Как? Уже все рассмотрел. Там вроде просто k-v

у него можно получить все варианты в случае конфликта. Погугли «riak allow_mult»

maxcom ★★★★★
()
Ответ на: комментарий от maxcom

Но это же разруливание конфликта на клиенте. Мне же еще нужно списки сохранять. А они простой k-v, тоесть для списков нужно делать еще навигацию. В Cassandra/Dynamo у меня будет природный список внутри low level row, что нумеруется второй частью композитного ключа CQL. Оно даже на диске упорядоченное

vertexua ★★★★★
() автор топика
Последнее исправление: vertexua (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.