2009-02-11 55 views
2

一些方面的问题如何实现脱机读写锁

  • 在这个问题上的所有对象是持久的。
  • 所有请求都将来自Silverlight客户端通过二进制协议(Hessian)而不是WCF与应用服务器通信。
  • 每个用户都有一个会话密钥(不是ASP.NET会话),它将是一个字符串,整数或GUID(到目前为止尚未确定)。

某些对象可能需要很长时间才能编辑(30分钟或更长时间),因此我们决定使用悲观离线锁定。因为必须协调冲突对于用户来说太烦人了,因为客户端并没有永久连接到服务器,所以很悲观。

而不是存储会话/对象加锁的对象本身我已决定的信息可能已它的实例锁定任何聚合根应该实现ILockable接口

public interface ILockable 
{ 
    Guid LockID { get; } 
} 

这LockID将是一个标识“锁定“对象,该对象保存哪个会话正在锁定它的信息。

现在,如果这是简单的悲观锁定,我将能够非常简单地实现这一点(使用Lock上的递增版本号来识别更新冲突),但我真正需要的是ReaderWriter悲观离线锁定。

的原因是,应用程序的某些部分将执行阅读这些复杂结构的动作。这些包括像

  • 阅读一个单一的结构克隆它。
  • 读取多个结构以创建二进制文件以将数据“发布”到外部源。

读取锁将保持一段非常短的时间,通常小于一秒,尽管在某些情况下他们可能会被猜测持续约5秒钟。

写锁定大多会保持较长时间,因为他们大多是由人类举行。

有一个高概率的两个用户试图在同一时间内编辑同一集合,许多用户需要暂时读锁在同一时间太的概率高。我正在寻找关于如何实现这一点的建议。

一个额外的点要提出的是,如果我想将一个写锁,有一些读锁,我想“队列”写入锁定,以便没有新的读锁放置。如果读取的锁定在X秒后被移除,则获得写入锁定,如果不是,则锁定写回锁定;写入锁排队时,不会放置新的读取锁。

到目前为止,我有这个想法

  1. 锁对象将有一个版本号(INT),这样我就可以检测多次更新冲突,重新加载,再试一次。
  2. 它将具有用于读锁定的字符串[]
  3. 持有具有写锁定
  4. 的字符串保持排队的写锁定
  5. 可能是递归计数器,以允许相同的会话ID的字符串会话锁定多次(对于读锁和写锁),但还不确定。

规则:如果有一个写锁或排队写锁定

  • 不能放置一个读锁定。
  • 如果存在写入锁定或排队写入锁定,则不能放置写入锁定。
  • 如果根本没有锁,则可以放置写入锁。
  • 如果有读取锁定,则写入锁定将排队,而不是放置完整写入锁定。 (如果在X时间之后读锁没有消失,则锁定关闭,否则将升级)。
  • 无法对具有读锁定的会话写入锁定队列。

任何人都可以看到任何问题吗?建议替代品?什么?在决定采取什么方法之前,我会很感激。

回答

1

你有没有考虑一个mvcc实现:

当然,这将是很难实现,但似乎更多的并发比你解释什么。只是把想法扔到那里。

+0

在这种情况下它不会是一个可以接受的方法,谢谢:-) – 2009-02-11 19:56:32

1

(编辑成措辞更作为一个答案,而不是一大堆的问题)

我回答这个雅虎DDD名单上为好,但可能还有这里也为了保持完整性。

你没有明确提到(我可以看到)任何种类的写入锁定超时。我知道他们可以被关押很长一段时间,但这会是一种谨慎的策略,可能会出现某种超时(即使它带有通知)。除了那个(或者甚至是那个),你可能想要考虑有一种手动释放锁的方法,如果你还没有考虑到 - 取决于系统的用户/角色,可能是某种类型的易于使用的管理界面。

另外,你也毫无疑问地想到了这一点,确保读锁数组是线程安全的。

+0

它不会需要是线程安全的,因为所涉及的对象是持久的,将被加载到不同的对象空间。我只需要检查更新时的冲突。 至于暂停。工作线程将检查超时并释放锁。 – 2009-02-12 09:10:36