Стратегии высокопроизводительной обработки транзакций - PullRequest
3 голосов
/ 09 ноября 2011

У меня есть система, которая имеет строгие требования «один раз и только один раз» в отношении того, что она делает.Это управляемая событиями система с промежуточным программным обеспечением, которая не может гарантировать один и только один раз обмен сообщениями (она помечает любое данное сообщение как «доставленное», если сомневается, является ли это повторной доставкой).Обработка «один раз и только один раз» в основном сводится к состоянию нашего основного предметного объекта, то есть это довольно стандартная установка, при которой ....

  1. сообщения прибывают
  2. бизнес-логикавыполняется
  3. состояние обновляется
  4. выходные данные генерируются и отправляются в нисходящие системы

3 должен в конечном итоге попасть в базу данных (книги и записи), 4 может занятьразличные формы, но все они являются своего рода сообщениями для внешних систем.Существует множество других потоков, но все они сводятся к такому стилю обработки.Все сообщения будут работать с одним экземпляром объекта основного домена, и поэтому обработка может быть привязана к этому экземпляру к одному jvm.

Мой Q довольно общий, возможно, слишком общий, но я все равно спрошу.А именно, какие стратегии / модели можно использовать для увеличения пропускной способности при сохранении требуемых гарантий?Кроме того, каковы основные ошибки, которые убивают производительность?

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

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

Обратите внимание, что это java / oracle в условиях большого предприятия, поэтому нишевое оборудование (например, exadata & friends или какой-то необычный сетевой комплект)Это хорошо.

Ответы [ 3 ]

2 голосов
/ 09 ноября 2011

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

Основной шаблон, который вам нужен, это шаблон актера. Чтобы увеличить пропускную способность, вы должны иметь возможность прозрачно пакетировать данные как часть вашего проекта. Лично мне нравится работать с прямыми байтовыми буферами (большая часть данных не находится в куче), поскольку они представляют собой легкий способ работы с большими объемами данных, которые можно легко копировать и читать / записывать на каналы NIO. Я написал свои собственные библиотеки синтаксического анализа / логирования для ввода / вывода без gc.

Еще одна полезная стратегия - предварительное распределение и утилизация объектов. Это может помочь устранить риск GC, не создавая мусор (или создавая только очень небольшое количество, которое можно собирать один раз в день)

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

Основными факторами, способными снизить производительность, являются

  • IO, вы хотите, чтобы это было асинхронно.
  • чрезмерная блокировка
  • создание большого количества объектов приведет к низкой эффективности кэша (поскольку новые объекты эффективно прокручивают ваши полезные данные) Переработанный объект может оставаться в кэше.
  • GC может навредить вам в худшем случае. Если вам важна только пропускная способность, это не имеет значения.
  • убедитесь, что вы подогреваете свой код. По умолчанию вам нужно выполнить 10000 вызовов метода (или иметь цикл, который повторяет это много раз) за короткий период, чтобы запустить его для компиляции. Если у вас низкая задержка, но не высокая пропускная способность, большие части критического кода могут не скомпилироваться.
  • убедитесь, что вы используете приличное оборудование и используете последнюю версию Java. Старые машины и старые версии Java могут быть немного медленнее.
1 голос
/ 09 ноября 2011
  • Какие стратегии / шаблоны можно использовать для увеличения пропускной способности при сохранении требуемых гарантий?

Не уверен, что я легко сопоставлю этот вопрос с "once and only once" requirements Вы имеете в виду, но я все равно это сделаю.

подход, основанный на событиях / не блокирующий, который я считаю уже "своего рода" в вашем потоке, судя по messages arrive.Представьте себе автономные / неизменные компоненты, которые могут принимать сообщения и реагировать в зависимости от типа / полезной нагрузки сообщения. Давайте на мгновение назовем эти компоненты actors.Тогда ваш поток станет:

сообщения поступят

субъекту

бизнес-логика

выполняется в состоянии без состояния method, которое соответствует / соответствуетсостояние этого сообщения

обновляется

state может быть простым файлом / RDBMS / NoSQL / памятью, который зависит только от вашей архитектуры =>, определяемой бизнесом.

Итак, тот же самый method может вызвать store.update() или просто отправить другое сообщение (например, UpdateStatus) в StatusActor, поэтому мы не блокируем / не блокируем [это будет зависеть от того, генерирует ли update =>=> send downstream "должен быть атомарным или нет]

выходы генерируются и отправляются в нисходящие системы

теперь субъект отправляет другое сообщение (например, GenerateOutput) другому субъекту, который генерирует выход, иотправляет другое сообщение (например, SendDownstream) другому действующему лицу.

  • В качестве альтернативы, какие основные ошибки могут снизить производительность?

Блокировка / Блокировкаи .. Преждевременная оптимизация

0 голосов
/ 09 ноября 2011

Это "довольно" легко, "просто" сделать ваши операции идемпотентными и подтвердить все операции.

...