免责声明:我已经问过了 这个问题, ,但没有部署要求。我得到了一个有3个投票的答案,当我编辑问题以包括部署要求时,答案随后变得无关紧要。我重新提交的原因是因为我认为最初的问题是“回答”,即使我没有有意义的投票答案。我开了一个 提交Uservoice 关于这个问题。我重新发布的原因是让 StackOverflow 考虑已回答的原始问题,因此它不会显示在“未回答的问题”选项卡上。

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

要求是:

  1. 不同进程/机器可以看到的互斥(锁)
  2. 锁定...释放语义
  3. 一定超时后自动释放锁 - 如果锁持有者死亡,它将在 X 秒后自动释放
  4. Java实现
  5. 轻松部署 - 不得要求超出 Netapp、MySql 或 GigaSpaces 的复杂部署。必须与这些产品配合良好(尤其是 GigaSpaces - 这就是 TerraCotta 被排除的原因)。
  6. 很高兴有:.Net 实现
  7. 如果是免费的:死锁检测/缓解

我对“它可以通过数据库完成”或“它可以通过 JavaSpaces 完成”之类的答案不感兴趣 - 我知道。相关答案应该只包含现成的、开箱即用的、经过验证的实现。

有帮助吗?

解决方案

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

创建一个锁定类,其中包含 SpaceID+SpaceRouting 属性 IDing 锁定的内容和 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对象。ID 缺少 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.");
        }
    }

其他提示

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

您可以在随产品提供的 gs-openspaces-src.zip 文件中找到该 Java 类的源代码。与 Gigaspaces .Net API 相同应该是直接的。

如果您仍在寻找,请看一下 阿帕奇动物园管理员:

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

Zookeeper 文档提供了以下示例 如何构建Lock服务 在 Zookeeper 之上。

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

假设1:

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

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

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

在重复的键更新键= key上插入Distributed_lock(key)值(#{key})中的distributed_lock(key)值(#{key});

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top