0

Распределённый контроль параллелизма

9

Я работал над этой проблемой уже несколько дней и нашел несколько решений, но ни одно из них не кажется особенно простым или легковесным. Проблема заключается в следующем: у нас есть кластер из 10 машин, каждая из которых работает с одинаковым программным обеспечением на многопоточном ESB-платформе. Я довольно легко справляюсь с проблемами параллелизма между потоками на одной машине, но что насчет конкуренции при работе с одними и теми же данными на разных машинах?

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

Решения, которыми я концептуально думал о том, чтобы воспользоваться:

  1. Использовать нашу отказоустойчивую общую файловую систему для создания "lock" файлов, которые будут проверяться каждой машиной в зависимости от клиента.
  2. Использовать специальную таблицу в нашей базе данных и блокировать всю таблицу для выполнения "тестирования и установки" записи блокировки.
  3. Использовать Terracotta, программное обеспечение с открытым исходным кодом, которое помогает в масштабировании, но использует модель "хаб и спицы".
  4. Использовать EHCache для синхронной репликации моих "замков" в памяти.

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

5 ответ(ов)

0

Вы сделали простую RMI-сервис с двумя методами: lock и release, которые принимают ключ (в вашей модели данных для первичных ключей используются UUID, что также соответствует ключу блокировки).

Использование RMI — это хорошее решение, потому что оно централизованное. Это не так легко реализовать с EJB (особенно в кластерной среде, где вы не знаете, на какой машине окажется ваш вызов). К тому же, это довольно просто.

В вашем случае это сработало — отличный подход!

0

Мы используем Terracotta, поэтому я бы хотел проголосовать за него.

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

Также я слышал о Zookeeper, который возник в Yahoo и теперь находится под эгидой Hadoop. Если вы готовы поэкспериментировать с новой технологией, она действительно имеет многообещающие перспективы, так как очень легкая и компактная, сосредоточенная исключительно на координации. Мне нравится её концепция и потенциал, хотя она может быть еще слишком "зеленой".

0

Я бы посоветовал использовать memcached в качестве очень быстрого, распределенного хранилища в оперативной памяти для хранения логов. Однако, похоже, что EHCache - это аналогичный проект, который более ориентирован на Java.

Оба варианта подходят, главное, чтобы вы использовали атомарные обновления (memcached это поддерживает, насчет EHCache не уверен). Это безусловно наиболее масштабируемое решение.

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

0

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

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

0

Не совсем sure, что понимаю весь контекст, но похоже, у вас есть одна база данных, которая все это поддерживает? Почему бы не воспользоваться блокировкой базы данных: если создание клиента — это единичный INSERT, то это выражение само по себе может служить блокировкой, так как база данных отклонит второй INSERT, который нарушает одно из ваших ограничений (например, уникальность имени клиента).

Если операция "вставка клиента" не атомарна и состоит из пачки операторов, то я бы предложил (или использовал) первоначальный INSERT, который создает какую-то простую запись, идентифицирующую вашего клиента (с необходимыми уникальными ограничениями), а затем выполнять все остальные вставки/обновления в той же транзакции. Вновь, база данных позаботится о согласованности, и любые параллельные изменения приведут к тому, что одно из них завершится неудачей.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь