【问题标题】:Implementing application level locking实现应用程序级锁定
【发布时间】:2011-07-23 02:28:35
【问题描述】:

我们的应用程序中有一个要求,即在访问/修改资源之前需要锁定资源,以避免并发操作并保持完整性。由于对资源执行了一系列操作,我们决定实现一个应用程序级锁定概念,所有访问该资源的组件都必须遵守该概念。

请注意,资源将被多个进程访问/修改,因此同步成为开销。这也是选择应用级锁定的原因之一。

我们想到的实现应用程序级锁定的方法之一是在数据库表中插入和更新条目,该表将包含资源名称、锁类型等列(可能是读锁、写锁或完全排他锁)和有关获取锁的进程的信息。我们选择数据库表作为一个选项,因为它是唯一一个集中到所有访问资源的进程的组件,但是如果有人可以探索其他可能性,那将会很有帮助。

数据库方法的另一个问题是实现必须使用悲观锁定。 (我们的应用程序使用 Oracle 作为我们的数据库服务器)。

这个问题的目的是探索实现应用程序级锁定的各种方法。

编辑 1

我之所以提到数据库方法必须实现悲观锁定是因为

  1. 各种应用组件访问/修改的资源由用户在软件中动态添加。因此,将它们的条目也始终插入此数据库表中会很丑陋。
  2. 即使在此表中创建了资源条目,我们何时删除这些条目也会出现问题?

乐观锁定方法本来不错,但我想不出我们如何实现它。

编辑 2 添加锁定类型的详细信息 我已经更新了上面的问题陈述,指定有3种锁类型

  1. 读取锁 - 如果所有其他锁都是读取或写入的,则可以获取
  2. 写排他锁 - 如果所有其他锁都被读取,则可以获取
  3. 完全排他锁 - 如果此资源上没有锁,则可以获得

【问题讨论】:

  • 您正在开发哪种应用程序(Web/GUI/CLI/等?)以及使用哪种编程语言?
  • 它是一个部署在 glassfish 集群上的 Web 应用程序。该应用程序正在使用 Java 编程语言开发

标签: locking


【解决方案1】:

您可能会为您的数据库样式锁定考虑的另一个字段是当前时间。您也可以考虑同意应用程序的任何操作不能超过 X 时间。

该建议背后的原因是为了防止出现可能的应用程序崩溃、失去与数据库的连接等情况以及无法“撤消”锁定的情况。其他应用程序将包括删除陈旧锁并创建新锁的功能。

您可能还希望应用程序插入该列,然后等待一段随机时间,然后再次尝试检查它。这有助于减少应用程序在等待数据库完成其操作时在资源上发生冲突的可能性。

【讨论】:

  • 感谢您的回复。您提到添加时间戳列的原因是我假设具有乐观锁定。由于我认为无法实现乐观锁定的原因,请查看我的上述编辑。关于恢复的第二点也是非常需要的,但我认为这可以通过有关获取资源锁定的进程的信息来完成。我不明白你关于插入新列的第三点。
  • 您提到“我们什么时候删除这些行?”在编辑中。这也是上面第二段的要点——让应用程序在发出锁时删除陈旧的锁。第三段是在两个应用程序尝试同时锁定同一资源时停止可能的竞争条件。随机时间以及第二次锁检查可能会阻止同时访问。
  • 我已更新问题描述以指定锁定类型的详细信息。抱歉稍后添加此信息。你能解释一下吗 1. 应用程序什么时候更新时间戳列? 2. 当不同的应用程序删除一个过时的锁并创建一个新的锁,同时对该资源有一个锁请求时,不会出现竞争条件。 3. 在您的第三段中,您提到应用程序插入了一个列。这个新专栏是干什么用的?
  • 此外,由于可以在同一资源上获取多个锁,因此同一资源必须有多行,因为如果每个资源只有一个条目,则维护进程信息变得困难。这引发了另一个问题,即使资源上的数据库操作原子化。为了实现原子性,我能想到的唯一解决方案是事先锁定表,这会降低并发性并增加等待时间。你认为有没有更好的方法来解决这个问题?再次感谢您的 cmets。
  • 在一个非常基本的层面上,我的设想是这样的:应用程序启动,在数据库中插入一行信息,如应用程序的 PID、应用程序的名称(人类可读)、时间戳的锁。然后它会等待 1 到 5 秒之间的随机时间。那时,它会检查另一个程序是否比插入的程序更早拥有锁。如果是这样,它将删除锁定请求并进入睡眠状态以稍后重试。否则,它会认为自己是唯一的锁定应用程序并且可以正常工作。这应该有助于减少由于数据库延迟等导致的竞争条件。
猜你喜欢
  • 2017-02-06
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 2015-09-15
  • 1970-01-01
相关资源
最近更新 更多