Распределенная служба блокировки через MySQL / GigaSpaces / Netapp [закрыта]
-
21-08-2019 - |
Вопрос
Отказ от ответственности:Я уже спрашивал этот вопрос, но без требования развертывания.Я получил ответ, который получил 3 голоса "За", и когда я отредактировал вопрос, чтобы включить требование к развертыванию, ответ тогда стал неактуальным.Причина, по которой я отправляю повторно, заключается в том, что SO считает что на исходный вопрос "дан ответ", даже хотя я не получил значимого поддержанного ответа.Я открыл пользовательский голос отправка об этой проблеме.Причина, по которой я перепостил, заключается в том, что StackOverflow считает исходный вопрос ответом, поэтому он не отображается на вкладке "вопросы без ответов".
Какую службу распределенной блокировки вы бы использовали?
Требования следующие:
- Взаимное исключение (блокировка), которое можно увидеть из разных процессов / машин
- заблокировать...семантика освобождения
- Автоматическое снятие блокировки по истечении определенного времени ожидания - если держатель блокировки умирает, он автоматически освобождается через X секунд
- Реализация Java
- Простое развертывание - не должно требовать сложного развертывания за пределами Netapp, MySQL или GigaSpaces.Должно хорошо сочетаться с этими продуктами (особенно GigaSpaces - вот почему TerraCotta была исключена).
- Приятно иметь:Реализация .Net
- Если это бесплатно:Обнаружение взаимоблокировки / смягчение ее последствий
Меня не интересуют ответы типа "это можно сделать через базу данных" или "это можно сделать через JavaSpaces" - я знаю.Соответствующие ответы должны содержать только готовую, "из коробки", проверенную реализацию.
Решение
Вот схема ответа на основе GigaSpaces, который соответствует вашим критериям, в зависимости от того, что именно вы имеете в виду в критерии 3.Я работаю с GigaSpaces из .Net, а не Java:
Создайте блокирующий класс со свойством SpaceID + SpaceRouting, указывающим, что заблокировано, и разблокированным свойством DataMember bool:
sealed public class IdLockTrans
{
[SpaceID]
[SpaceRouting]
public string ID
{
get;
set;
}
[DataMember]
public bool Unlocked
{
get;
set;
}
public IdLockTrans(Id id)
{
ID = id.ID;
}
public IdLockTrans()
{
}
}
Вы будете использовать время аренды GigaSpaces для снятия блокировки по истечении определенного тайм-аута.Это приведет к тому, что GigaSpaces автоматически удалит объекты IdLockTrans из пространства после того, как они простаивали в течение времени ожидания .Отсутствие IdLockTrans для идентификатора означает, что идентификатор разблокирован.
Ваш класс locker определит и инициализирует эти члены класса
private readonly ISpaceProxy _proxy;
private readonly long _leaseTime;
public override bool Lock(Id id, long timeout)
{
bool locked;
IdLockTrans lockTransTemplate = new IdLockTrans(id);
// Assume that this is a new id.
try
{
_proxy.Write(lockTransTemplate, null, _leaseTime, 0, UpdateModifiers.WriteOnly);
locked = true;
}
catch (EntryAlreadyInSpaceException)
{
using (ITransaction tx = _proxy.CreateLocalTransaction())
{
try
{
lockTransTemplate.Unlocked = true;
IdLockTrans lockTrans = _proxy.Take(lockTransTemplate, tx, timeout);
locked = (lockTrans != null);
if (lockTrans != null)
{
lockTrans.Unlocked = false;
_proxy.Write(lockTrans, tx, _leaseTime, 0, UpdateModifiers.WriteOnly);
}
tx.Commit();
}
catch
{
tx.Abort();
throw;
}
}
}
return locked;
}
public override void Unlock(Id lockedId)
{
IdLockTrans lockTrans = new IdLockTrans(lockedId);
lockTrans.Unlocked = true;
try
{
_proxy.Update(lockTrans, null, _leaseTime, 0, UpdateModifiers.UpdateOnly);
}
catch (EntryNotInSpaceException)
{
throw new Exception("IdLockTrans for " + lockTrans.ID
+ " not found on Unlock. Lock time exceeded lease time.");
}
}
Другие советы
Ваша реализация .Net очень близка к существующему готовому API блокировки / разблокировки, предоставляемому вместе с Java API.Видишь:http://www.gigaspaces.com/docs/JavaDoc8.0/org/openspaces/core/DefaultGigaMap.html
Возможно, вы нашли исходный код для этого класса Java как часть файла gs-openspaces-src.zip, поставляемого вместе с продуктом.Использование того же самого с Gigaspaces .Net API должно быть прямым.
На случай, если вы все еще смотрите, взгляните на Хранитель зоопарка Apache:
ZooKeeper - это централизованный сервис для хранения информации о конфигурации, присвоения имен, обеспечения распределенной синхронизации и предоставления групповых сервисов.Все эти виды сервисов в той или иной форме используются распределенными приложениями.
Документация Zookeeper содержит примеры как создать службу блокировки на вершине Смотрителя зоопарка.
Использовать mysql для блокировки уникального ключа очень просто.
Предположение 1:
Вы используете транзакцию, и ваш уровень изоляции зафиксирован для чтения.
Предположение 2:Вы блокируете обрабатывающий поток уникальным ключом и освобождаете его, когда ваша транзакция фиксируется.
Затем вы можете использовать этот sql в качестве блокировки распространения:
Вставить в distributed_lock(ключ) значения (#{ключ}) ПРИ ДУБЛИРОВАНИИ КЛЮЧА ОБНОВИТЬ ключ=ключ;