Обмен синхронизированным блоком Java через кластер или использование глобальной блокировки?

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

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

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

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

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

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

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

Спасибо!

Ответы

Ответ 1

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

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

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

Обновление (8/4/2009 2:39 PM). Я предлагаю LOCK TABLE для некоторых таблица, содержащая версию № схемы. Это приведет к сериализации доступа к этой таблице, предотвращая одновременное выполнение двумя экземплярами кода обновления.

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

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

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

Ответ 5

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