代码之家  ›  专栏  ›  技术社区  ›  Community wiki

MySql/GigaSpaces/Netapp上的分布式锁服务[已关闭]

  •  1
  • Community wiki  · 技术社区  · 2 年前

    免责声明 :我已经问过了 this question ,但没有 部署要求。我得了 得到3张赞成票的答案,当我 编辑问题以包括部署要求然后回答 变得无关紧要。我的原因 重新提交是因为SO考虑 最初的问题“得到了回答”,甚至 尽管我没有得到有意义的支持 答复我打开了一个 uservoice submission 关于这个问题。 我转发的原因是,StackOverflow考虑到了原来的问题,所以它不会出现在“未回答的问题”选项卡上。

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

    要求是:

    1. 可以从不同的进程/机器中看到的互斥(锁)
    2. 锁发布语义
    3. 超时后自动解锁-如果锁夹死亡,X秒后自动解锁
    4. Java实现
    5. 易于部署 -不得要求在Netapp、MySql或GigaSpaces之外进行复杂的部署。必须很好地使用这些产品(尤其是GigaSpaces——这就是TerraCotta被排除在外的原因)。
    6. 很高兴拥有:.Net实现
    7. 如果是免费的:死锁检测/缓解

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

    4 回复  |  直到 9 年前
        1
  •  4
  •   Shay Hassidim    13 年前

    您的.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
  •  1
  •   Mark Nelson    16 年前

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

    创建一个具有SpaceID+SpaceRouting属性标识锁定内容和DataMember布尔属性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已解锁。

    您的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.");
            }
        }
    
        3
  •  0
  •   Matt B    15 年前

    如果你还在看,看看 Apache Zookeeper :

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

    Zookeeper文档提供了以下示例 how to build a Lock service 在动物园管理员的上面。

        4
  •  0
  •   易天明    8 年前

    使用mysql锁定一个唯一的密钥非常简单。

    假设1:

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

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

    然后,您可以将此sql用作分布式锁:

    插入分布式锁(钥匙) 重复密钥上的值(#{key})UPDATE key=key;