Почему база данных как очередь так плохо? [закрыто]

33

Я только что прочитал эту статью , и я в замешательстве.

Давайте представим 1 веб-приложение и 1 отдельное приложение, выступающие в роли «работника», которые совместно используют одну и ту же базу данных .

О, я сказал "делиться" .. но о чем статья предупреждает? :

В-четвертых, разделение базы данных между приложениями (или службами) - это плохо. Просто слишком заманчиво помещать аморфное общее состояние туда, и, прежде чем вы это узнаете, у вас будет чудовищно связанный монстр.

=> не согласен. В некоторых случаях отдельные приложения все еще являются частью одного и того же устройства, и, следовательно, понятие «проблема соединения» не имеет смысла в этом случае.

Давайте продолжим: веб-приложение обрабатывает клиентские HTTP-запросы и может в любое время обновлять некоторые агрегаты (термин DDD), генерируя соответствующие доменные события.
Целью работника будет обработка этих событий домена путем обработки необходимых заданий.

Дело в том:

Как данные о событиях должны быть переданы работнику?

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

Рабочий процесс будет простым:

Каждый раз, когда веб-dyno генерирует событие, оно публикует его через RabbitMQ, который передает работнику.
Недостатком было бы то, что ничто не гарантирует немедленной согласованности между фиксацией совокупного обновления и публикацией события, не имея дело с потенциальными сбоями отправки ... или аппаратными проблемами; это еще одна главная проблема.

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

Итак, что может быть хорошим решением для обеспечения этой немедленной согласованности? :
IMO, хранящий событие в базе данных, в той же локальной транзакции, что и сводное обновление.
Будет создан простой асинхронный планировщик, который будет отвечать за запросы текущих неопубликованных событий из базы данных и отправлять их в RabbitMQ, который, в свою очередь, заполняет рабочий.

Но зачем нужен дополнительный планировщик на стороне веб-приложения и, между прочим, зачем нужен RabbitMQ в этом случае?

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

Поэтому мне интересно, почему так много статей в Интернете критикует организацию очередей баз данных, в то время как продвигает промежуточное ПО, ориентированное на сообщения.

Выдержка из статьи:

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

А немедленная согласованность игнорируется?

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

Я пропустил некоторые критические понятия?

Благодарность

Mik378
источник
2
Опрос - это своего рода красная сельдь, потому что почти во всех основных базах данных есть некоторый механизм для асинхронного уведомления какого-то другого процесса о том, что пришло время вытащить некоторую работу из таблицы.
Blrfl

Ответы:

28

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

Системы на основе очередей, такие как RabbitMq, построены в широком масштабе на умеренном оборудовании. Их архитектура способна достичь этого, избегая процессов, которые делают ACID- совместимую систему баз данных медленной по своей природе. Так как шина сообщений должна только гарантировать, что сообщение сохранено и успешно обработано, ей не нужно беспокоиться о блокировке и записи журналов транзакций. Обе эти концепции абсолютно необходимы для системы ACID, но часто являются причиной раздоров.

С точки зрения производительности это сводится к тому, что у вас есть таблица SQL. Много читает и много пишет. Оба требуют какой-то блокировки для обновления строк, страниц и индексов. Ваш механизм опроса постоянно блокирует индекс для поиска по нему. Это препятствует тому, чтобы записи происходили; в лучшем случае они стоят в очереди. Код, выполняющий обработку, также блокируется, чтобы обновить состояние в очереди по мере их завершения или сбоя. Да, вы можете выполнить оптимизацию запросов после оптимизации, чтобы заставить это работать, или вы можете использовать систему, специально предназначенную для рабочей нагрузки, которую вы запрашиваете. RabbitMq поглощает этот тип рабочей нагрузки, даже не потея; Кроме того, вы можете сохранить свою базу данных от рабочей нагрузки, предоставляя ей больше возможностей для масштабирования и выполнения других задач.

Еще одна вещь, которую следует учитывать, - большинство систем очередей, как правило, не используют метод опроса (некоторые допускают HTTP, но рекомендуют избегать использования для принимающей стороны). RabbitMq использует сетевые протоколы, специально разработанные для шин сообщений, таких как AMPQ .

Изменить: Добавление варианта использования.

Как я использовал Rabbit, у меня была конечная точка API, которая принимает изменение, которое требует интенсивно используемой таблицы базы данных. Эта таблица постоянно находится в споре, и иногда она не сможет своевременно сохранить изменения из API. Вместо этого я пишу запрос на изменение в очередь, а затем создаю службу, которая обрабатывает эти сообщения, как только может. Если возникает конфликт базы данных, очередь просто увеличивается, и обработка сообщений задерживается. Обычно время обработки в диапазоне 14 мс, но во время высокой конкуренции мы получаем до 2-3 секунд.

brianfeucht
источник
Как вы могли бы справиться с немедленным собранием в этом случае? Если публикация будет произведена, но сразу после этого, транзакция, ответственная за обновление откатов модели домена ... Промежуточное ПО будет полностью не осведомлено и обработает событие.
Mik378
Вы написали: «Не нужно беспокоиться о блокировке». Но, безусловно, существует своего рода блокировка для обеспечения восходящего порядка (во времени) перенаправленных событий (по направлению к работнику), не так ли?
Mik378
@ Mik378 Взгляните на эту статью о идемпотентности сообщений . Да, технически вы теряете некоторое обещание согласованности, но держу пари, что вы найдете то, что вы получите с точки зрения надежности времени безотказной работы приложения и производительности, оно того стоит. Также довольно легко изменить способ обработки сообщений, чтобы потери были достаточно безболезненными.
Брианфойхт
2
Да, вам потребуется блокировка для гарантии заказа. Некоторые системы очередей могут обеспечить это за счет производительности. Если вы можете принять тот факт, что иногда операции происходят не по порядку, и найти способ справиться с этим на стороне процессора, вы выиграете в геометрической прогрессии с точки зрения производительности.
Брианфойхт
1
@ Mik378 - я добавил вариант использования в свой ответ. Я надеюсь, что это помогает!
Брианфойхт