锁定分布式系统中的文件

时间:2013-10-07 16:11:56

标签: database windows multithreading parallel-processing cifs

我有一个分布式应用程序;也就是说,我有一个在多台计算机上运行的同类进程,它与中央数据库通信并访问网络文件共享。

此过程从网络文件共享(通过CIFS)中获取集合文件,对这些文件运行转换算法并将输出复制回网络文件共享。

我需要锁定输入文件,以便运行相同进程的其他服务器无法在同一文件上运行。为了论证,假设我的描述过于简单,并且锁是绝对必须的。

以下是我提出的解决方案和一些想法。

1)使用机会锁(oplocks)。此解决方案仅使用文件系统来锁定文件。这里的问题是我们必须尝试获取锁定以确定锁是否存在。这似乎是昂贵的,因为网络重定向器协商锁。关于这一点的好处是可以以这样的方式创建oplock,以便在出现错误时自行删除。

2)使用数据库应用程序锁(通过sp_getapplock)。这似乎会快得多,但现在我们正在使用数据库来锁定文件系统。此外,数据库应用程序锁定可以通过事务或会话确定范围,这意味着如果我想保留 - 以及稍后释放 - 应用程序锁定,我必须保持连接。目前,我们正在使用连接池,这必须改变,这可能是一个更大的对话本身。这种方法的好处是,如果我们失去与服务器的连接,锁将被清除。当然,这意味着如果我们失去与数据库的连接,而不是网络文件共享,那么当我们仍在处理输入文件时,锁就会消失。

3)创建一个数据库表和存储过程来表示我想要锁定的项目。这个过程很简单。这方面的缺点当然是潜在的网络错误。如果由于某种原因,数据库无法访问,则锁定将保持有效。然后我们需要派生一些算法来在以后清理它。

最佳解决方案是什么?为什么?答案不限于上面提到的那些。

1 个答案:

答案 0 :(得分:1)

根据您的情况,您应该使用共享模式锁。这正是它们的目的。

Oplocks不会是你想要的 - 一个oplock不是一个锁,并不会阻止任何人做任何事情。这是一种通知机制,让客户机知道是否有人访问该文件。这通过“破坏”你的oplock传达给机器,但这不是进入应用程序层(即你的代码)的东西 - 它只是生成一条消息给客户端操作系统告诉它使它的缓存无效从服务器再次复制和获取。

请参阅MSDN:

当另一个进程打开您持有oplock的文件时,会发生什么情况的说明在这里:

但重要的是,oplock不会阻止打开文件的其他进程,它们只允许客户端计算机之间的协调。因此,oplock不会在应用程序级别锁定文件 - 它们是网络文件系统堆栈用于实现缓存的网络协议的一项功能。它们并不适用于要使用的应用程序。


由于您在Windows上编程,因此适当的解决方案似乎是共享模式锁定,即使用SHARE_DENY_READ|SHARE_DENY_WRITE|SHARE_DENY_DELETE打开文件。

如果CIFS服务器上不支持共享模式锁,您可能会考虑flock()类型锁。 (以传统的Unix技术命名)。

如果您正在处理xyz.xml,请创建名为xyz.xml.lock的文件(使用CREATE_NEW模式,这样您就不会破坏现有文件)。完成后,将其删除。如果由于文件已存在而无法创建文件,则表示另一个进程正在处理该文件。将信息写入锁定文件可能很有用,这对调试很有用,例如servername和PID。您还必须有一些清理废弃锁文件的方法,因为这不会自动发生。

如果CIFS是一个复制系统,那么数据库锁可能是合适的,这样flock()锁就不会在整个系统中以原子方式发生。否则我会坚持使用文件系统,因为只有一件事可能出错。