在从文件中读取行并处理它们时,我在某些代码中使用了文件系统锁。这是因为我的架构有多个应用服务器;我只希望一台服务器处理每一行以避免数据重复。
我在辅助方法中创建了一个DTO。该对象使用锁定详细信息填充,该详细信息可以由辅助方法返回,并且可以随后查询以查看锁定是否成功。如果是,则可以处理文件中的行。
通常,如果两个服务器同时尝试并处理文件中的行,则其中一个服务器会抛出异常,因为该文件已被另一个文件锁定。如果发生这种情况,我的代码会捕获异常并移动到文件的下一行。
锁定在下面实现:
String filename = <Unique identifier of record being processed>;
File lockfile = new File(System.getProperty("java.io.tmpdir"), filename);
RandomAccessFile randomAccessfile = new RandomAccessFile(lockfile, "rw");
FileChannel fileChannel = randomAccessfile.getChannel();
FileLockDTO fileLockDTO = new FileLockDTO();
fileLockDTO.setLockedfile(lockfile);
fileLockDTO.setRandomAccessfile(randomAccessfile);
fileLockDTO.setFileLock(fileChannel.tryLock());
在绝大多数情况下,代码运行良好。但是在极少数情况下会出现重复记录,这表明存在一个边缘情况,其中多个应用程序服务器似乎在同一时刻创建锁。
我长得很长努力学习代码并尝试了大量的测试,但无法确定这将如何发生。只是想知道是否有人有任何想法?
提前感谢您的任何帮助。
答案 0 :(得分:-1)
来自FileLock
javadocs:
锁是否实际阻止其他程序访问锁定区域的内容是系统相关的,因此未指定。某些系统的本机文件锁定工具仅仅是建议性的,这意味着程序必须协作地观察已知的锁定协议,以保证数据的完整性。
来自FileChannel.tryLock()
javadocs :(重点是我的)OverlappingFileLockException
被抛出
如果与此请求区域重叠的锁已由此Java虚拟机保留,或者另一个线程已在此方法中被阻止并且正在尝试锁定重叠区域
以下是您的应用的简单失败方案:
tryLock()
的调用可能无法阻止任何事情)答案 1 :(得分:-1)
你必须依赖FileLockDTO.setFileLock()中的null检查,或者你拥有它的任何地方,如果确实你拥有它。这一切对我来说似乎太精致了。我只想锁定你正在阅读的实际文件的实际行,而不是引入这些二级锁文件。然后,如果您遇到现有锁,您就会跳过该行。或者使用一种数据结构,它只能传递一行,并消除整个问题,例如某种类型的MQ或数据库。
编辑关于FileLocks无法跨JVM或进程工作的理论的下载者和/或拥护者需要阅读文档。