【问题标题】:Distributed Lock Service over MySql/GigaSpaces/Netapp [closed]MySql/GigaSpaces/Netapp 上的分布式锁服务 [关闭]
【发布时间】:2009-07-01 17:54:52
【问题描述】:

免责声明:我已经问过this question,但没有 部署要求。我有一个 得到 3 个赞成票的答案,当我 编辑问题以包括部署要求然后回答 变得无关紧要。我的原因 重新提交是因为 SO 认为 原来的问题“回答”了,甚至 虽然我没有得到有意义的支持 回答。我就这个问题开了uservoice submission。 我重新发布的原因是 StackOverflow 认为原始问题已回答,因此它不会显示在“未回答的问题”选项卡上。

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

要求是:

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

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

【问题讨论】:

  • 不明白你为什么不编辑其他问题,如果添加了符合你修改后要求的答案,接受;另一个答案是否有更多的赞成票并不重要。通过对问题的编辑使某些答案变得无关紧要是很常见的(并且被接受)。
  • 因为它被视为“已回答”(赞成的回答),所以它不会显示在“未回答的问题”标签上。

标签: java mysql locking distributed gigaspaces


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    使用 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 对象 超时空闲后自动从空间 时期。 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.");
            }
        }
    

    【讨论】:

    • 这就是我最终实现的。我不能发布源代码,因为它是公司的财产,但这是一般的想法。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      使用mysql锁定唯一键很简单。

      假设 1:

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

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

      那么你可以使用这个sql作为distribute lock:

      插入distributed_lock(key) values(#{key}) ON DUPLICATE KEY UPDATE key=key;

      【讨论】:

        猜你喜欢
        • 2010-11-06
        • 1970-01-01
        • 2013-07-20
        • 1970-01-01
        • 1970-01-01
        • 2016-10-30
        • 2015-09-03
        • 1970-01-01
        • 2014-09-28
        相关资源
        最近更新 更多