MySql / GigaSpaces / Netapp上的分布式锁服务

时间:2009-07-01 17:54:53

标签: java mysql locking distributed gigaspaces

  

免责声明:我已经问过this question,但没有   部署要求。我有一个   答案得到3个赞成票,当我   编辑了问题以包含部署要求的答案   变得无关紧要。我之所以如此   重新提交是因为SO考虑   原来的问题“回答”,甚至   虽然我没有得到任何有意义的投票   回答。我打开了一个关于这个问题的uservoice submission。   我转发的原因是StackOverflow认为原始问题已经回答,所以它没有出现在“未答复的问题”标签上。

您将使用哪种分布式锁定服务?

要求是:

  1. 可以从不同进程/机器看到的互斥(锁定)
  2. lock ... release semantics
  3. 在某个超时后自动锁定释放 - 如果锁定持有者死亡,它将在X秒后自动释放
  4. Java实现
  5. 轻松部署 - 不得要求Netapp,MySql或GigaSpaces之外的复杂部署。必须与这些产品配合得很好(特别是GigaSpaces - 这就是排除TerraCotta的原因)。
  6. 很高兴:.Net实施
  7. 如果它是免费的:死锁检测/缓解
  8. 我对“它可以在数据库上完成”或“它可以在JavaSpaces上完成”等答案不感兴趣 - 我知道。相关答案应该只包含一个现成的,开箱即用的,经过验证的实现。

4 个答案:

答案 0 :(得分:4)

您的.Net实现与Java API提供的现有开箱即用锁定/解锁API非常接近。看到: http://www.gigaspaces.com/docs/JavaDoc8.0/org/openspaces/core/DefaultGigaMap.html

您可能会将此Java类的源代码作为产品随附的gs-openspaces-src.zip文件的一部分找到。与Gigaspaces .Net API相同应该是直接的。

答案 1 :(得分:1)

以下是基于GigaSpaces的答案的大纲,它符合您的标准,具体取决于您在标准3中的含义。我使用.Net的GigaSpaces,而不是Java:

创建一个带有SpaceID + SpaceRouting属性的锁定类,用于标识锁定的内容和DataMember bool属性Unlocked:

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对象 在空闲超时后自动从空间开始 期。缺少IDL的IdLockTrans意味着ID已解锁。

您的更衣室课程将定义并初始化这些班级成员

    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.");
        }
    }

答案 2 :(得分:0)

如果您还在寻找,请查看Apache Zookeeper

  

ZooKeeper是一种集中式服务,用于维护配置信息,命名,提供分布式同步和提供组服务。所有这些类型的服务都以分布式应用程序的某种形式使用。

Zookeeper文档在Zookeeper上提供了how to build a Lock service的示例。

答案 3 :(得分:0)

使用mysql锁定唯一键非常简单。

假设1:

您使用事务并且您的隔离级别被读取已提交。

假设2: 您通过唯一键锁定处理线程,并在提交事务时释放它。

然后你可以使用这个sql作为分发锁:

插入distributed_lock(密钥)         值(#{key})ON DUPLICATE KEY UPDATE key = key;