Совместное использование синхронизированного блока Java в кластере или использование глобальной блокировки? - PullRequest
16 голосов
/ 04 августа 2009

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

Целевой средой является WebSphere 6.0 с 2 узлами в кластере.

У меня такое ощущение, что synchronized не будет работать, поскольку каждый экземпляр приложения на каждом узле будет иметь свою собственную JVM, верно?

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

База данных - DB2v9, и я обращаюсь к ней напрямую через JNDI (без уровня ORM).

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

Есть ли у кого-нибудь указатели на этой арене?

Спасибо!

Ответы [ 5 ]

7 голосов
/ 04 августа 2009

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

Однако существуют способы заставить синхронизированные блоки работать в кластере так же, как они работают в среде с одним узлом. Самый простой способ - использовать такой продукт, как Terracotta , который будет обеспечивать координацию потоков между различными JVM, чтобы в кластере можно было использовать обычные средства управления параллелизмом. Есть много статей, объясняющих, как это работает, например, Введение в OpenTerracotta .

Конечно, есть и другие решения. Это в основном зависит от того, чего вы действительно хотите достичь здесь. Я бы не использовал блокировки базы данных для синхронизации, если вам нужно масштабировать, как DB не делает. Но я действительно призываю вас найти готовое решение, потому что возиться с синхронизацией кластера - дело грязное:)

5 голосов
/ 04 августа 2009

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

Правильный способ решения этой проблемы - это блокировки на уровне базы данных. Предположительно у вас есть какая-то таблица, которая содержит версию схемы БД, поэтому вы должны обязательно заблокировать эту таблицу на время процесса запуска / обновления.

Точные вызовы sql / db, вероятно, будут более понятными, если вы укажете тип вашей базы данных (DB2?) И метод доступа (raw sql, jpa и т. Д.).

Обновление (04.08.2009 14:39) : Я предлагаю инструкцию LOCK TABLE для некоторой таблицы, содержащей номер версии схемы. Это позволит сериализовать доступ к этой таблице, предотвращая одновременный запуск двух экземпляров кода обновления.

4 голосов
/ 06 ноября 2012

Для этого вы также можете использовать сетку данных в памяти, например http://www.hazelcast.com/. Это распределенная структура данных, которая поддерживает блокировку.

3 голосов
/ 04 августа 2009

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

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

  1. Добавить столбец для записи / версии строки.
  2. Пройдите логику, чтобы проверить, нужно ли обновлять запись.
  3. Когда вы обновляете запись, убедитесь, что версия записи в БД такая же, как у вас.
  4. Увеличивать версию каждый раз, когда вы пишете в базу данных.

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

0 голосов
/ 04 августа 2009

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

...