问题的某些背景
某些对象可能需要很长时间才能编辑(30分钟或更长时间),因此我们决定使用悲观的离线锁定。悲观,因为必须协调冲突对用户来说太烦人了,离线因为客户端没有永久连接到服务器。
我没有将会话/对象锁定信息存储在对象本身中,而是决定任何可能锁定其实例的聚合根应该实现一个接口ILockable
public interface ILockable
{
Guid LockID { get; }
}
此LockID将是“Lock”对象的标识,该对象包含哪个会话锁定它的信息。
现在,如果这是简单的悲观锁定,我将能够非常简单地实现这一点(使用Lock上的递增版本号来识别更新冲突),但我真正需要的是ReaderWriter悲观的离线锁定。
原因是应用程序的某些部分将执行读取这些复杂结构的操作。这些包括
之类的内容读取锁定将保持很短的时间,通常不到一秒钟,但在某些情况下,它们可以在猜测时保持约5秒钟。
写锁定大部分时间都会被保留,因为它们主要由人类持有。
两个用户同时尝试编辑同一聚合的概率很高,很多用户同时也需要暂时读取锁定的概率很高。我正在寻找关于如何实现这一点的建议。
要做的另一点是,如果我想放置一个写锁并且有一些读锁,我想“排队”写锁,这样就不会放置新的读锁。如果读取锁定在X秒内被移除,则获得写入锁定,如果没有,则写入锁定退出;写入锁定排队时不会放置新的读锁定。
到目前为止,我有这个想法
规则:
任何人都可以看到任何问题吗?建议替代方案?什么?在决定采取何种方法之前,我会很感激反馈。
答案 0 :(得分:1)
您是否考虑过mvcc实施:
当然,它实现起来会更难,但似乎比你解释的要多得多。把想法扔到那里。
答案 1 :(得分:1)
(编辑为更多的答案,而不是一堆问题)
我也在Yahoo DDD列表中回复了这个问题,但也可以在这里完整性。
你没有明确提到(我可以看到)任何类型的写锁定超时。我知道他们将能够被关押很长时间,但是如果出现某种超时(即使它附带通知),这将是一种谨慎的策略。
除非(或者甚至更好),您可能需要考虑使用一种方法来手动释放锁,如果您还没有考虑过 - 取决于系统的用户/角色,可能某种易于使用的管理界面。
另外,你也毫不怀疑这一点,确保读锁数组是线程安全的。
答案 2 :(得分:0)
如果你真的想要推出自己的锁定,我会遵循类似于线程锁定的锁定模式,例如在ReaderWriterLockSlim中。
http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx