Распределенная служба блокировки через MySQL / GigaSpaces / Netapp [закрыта]

StackOverflow https://stackoverflow.com/questions/1070495

Вопрос

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

Какую службу распределенной блокировки вы бы использовали?

Требования следующие:

  1. Взаимное исключение (блокировка), которое можно увидеть из разных процессов / машин
  2. заблокировать...семантика освобождения
  3. Автоматическое снятие блокировки по истечении определенного времени ожидания - если держатель блокировки умирает, он автоматически освобождается через X секунд
  4. Реализация Java
  5. Простое развертывание - не должно требовать сложного развертывания за пределами Netapp, MySQL или GigaSpaces.Должно хорошо сочетаться с этими продуктами (особенно GigaSpaces - вот почему TerraCotta была исключена).
  6. Приятно иметь:Реализация .Net
  7. Если это бесплатно:Обнаружение взаимоблокировки / смягчение ее последствий

Меня не интересуют ответы типа "это можно сделать через базу данных" или "это можно сделать через 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(ключ) значения (#{ключ}) ПРИ ДУБЛИРОВАНИИ КЛЮЧА ОБНОВИТЬ ключ=ключ;

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top