0

我们有一个 java 进程,它使用 apache commons vfs 监听文件系统上的目录 X。每当一个新文件被导出到这个目录时,我们的流程就会启动。我们首先将文件重命名为 filename.processing 并解析文件名,从文件中获取一些信息并插入到表中,然后将此文件发送到文档管理系统. 这是每个集群的单线程应用程序。现在考虑在集群环境中运行,我们有 5 个服务器。所以 5 个不同的虚拟机试图访问同一个文件。整个实现是基于在给定时间只有一个进程可以将文件重命名为 .processing ,因为操作系统不允许多个进程同时修改文件。一旦一个集群得到持有并将文件重命名为.processing,其他集群'

一年多以来一直运行良好,但刚才我们发现很少有重复项。看起来多个集群都掌握了文件,在这种情况下,集群 a、b、c 已经获得了文件 f.pdf 的访问权限,并且他们同时将其重命名为 f.pdf.processing,(我仍然感到困惑操作系统如何允许同时修改文件)。作为这些的结果,集群 a、b、c 他们处理了文件并将其发送到文档管理系统。所以现在有3个重复文件。

所以简而言之,我正在看的是,在集群环境中只运行一次任务的方法。我还希望它具有故障转移机制,这样如果集群出现问题,另一个集群会接手任务。我们不想在盒子上设置环境变量,比如 master=true,因为这会将它限制为只有一个集群并且不会处理故障转移。

任何形式的帮助表示赞赏。

4

3 回答 3

1

请参阅以下有关文件锁定的帖子:文件系统如何处理并发读/写?

正如您所假设的那样,文件的读写操作(包括重命名)不是原子的,并且在进程之间没有很好的同步 - 至少在大多数操作系统上不是这样。

但是,创建新文件通常是原子操作。你可以利用它来发挥你的优势。这个概念称为整体文件锁定。

于 2015-12-11T22:11:02.870 回答
1

我们正在使用应用程序数据库中的共享锁表来实现我们自己的同步逻辑。这允许所有集群节点在实际启动作业之前检查作业是否已经在运行。

于 2015-12-21T21:59:53.103 回答
0

在将文件重命名为 .processing 之前,您是否尝试使用FileLock tryLock() 或 lock()?如果你没有,我认为你应该尝试,所以在这种情况下,只有一个应用程序可以允许更改这个文件。

更新:对不起,我忘了你问的是 VDF。在 Apache VDF 中(事实上,在Apache Synapse中)我找到了 VFSUtils类,它有以下方法:

public static boolean acquireLock(org.apache.commons.vfs2.FileSystemManager fsManager,
                                  org.apache.commons.vfs2.FileObject fo)

Acquires a file item lock before processing the item, guaranteing that the file is not processed while it is being uploaded and/or the item is not processed by two listeners
Parameters:
   fsManager - used to resolve the processing file
   fo - representing the processign file item
Returns:
   boolean true if the lock has been acquired or false if not

我认为,该方法可以解决您的问题(如果您可以在项目中使用 Apache Synapse)。

于 2015-12-11T22:12:38.930 回答