基于 MySql/GigaSpaces/Netapp 的分布式锁服务 [关闭]
-
21-08-2019 - |
题
免责声明:我已经问过了 这个问题, ,但没有部署要求。我得到了一个有3个投票的答案,当我编辑问题以包括部署要求时,答案随后变得无关紧要。我重新提交的原因是因为我认为最初的问题是“回答”,即使我没有有意义的投票答案。我开了一个 提交Uservoice 关于这个问题。我重新发布的原因是让 StackOverflow 考虑已回答的原始问题,因此它不会显示在“未回答的问题”选项卡上。
您会使用哪种分布式锁服务?
要求是:
- 不同进程/机器可以看到的互斥(锁)
- 锁定...释放语义
- 一定超时后自动释放锁 - 如果锁持有者死亡,它将在 X 秒后自动释放
- Java实现
- 轻松部署 - 不得要求超出 Netapp、MySql 或 GigaSpaces 的复杂部署。必须与这些产品配合良好(尤其是 GigaSpaces - 这就是 TerraCotta 被排除的原因)。
- 很高兴有:.Net 实现
- 如果是免费的:死锁检测/缓解
我对“它可以通过数据库完成”或“它可以通过 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});