1

这是一个非常常见的场景:某个进程希望每 30 分钟左右在服务器上删除一个文件。很简单,对吧?好吧,我可以想到很多可能出错的方法。

例如,处理一个文件可能需要多于或少于 30 分钟,因此一个新文件可能会在我完成前一个文件之前到达。我不希望源系统覆盖我仍在处理的文件。

另一方面,文件很大,因此需要几分钟才能完成上传。我不想开始处理部分文件。这些文件只是通过 FTP 或 sftp(我的偏好)传输的,因此操作系统级别的锁定不是一种选择。

最后,我确实需要将文件保留一段时间,以防我需要手动检查其中一个(用于调试)或重新处理一个。

我见过很多临时的方法来改组上传文件、交换文件名、使用日期戳、触摸“指示符”文件以帮助同步等等。我还没有看到一个全面的“算法”,用于处理处理并发性、一致性和完整性的文件。

所以,我想在这里利用群众的智慧。有没有人见过一种真正防弹的方法来处理批处理数据文件,这样它们就不会过早处理,不会在完成之前被覆盖,并在处理后安全保存?

4

3 回答 3

1

关键是在发送端进行初始杂耍。发件人需要做的就是:

  1. 使用唯一的文件名存储文件。
  2. 文件发送后,立即将其移至名为 eg 的子目录completed

假设只有一个接收者进程,所有接收者需要做的是:

  1. 定期扫描completed目录中的任何文件。
  2. 只要文件出现在 中completed,就将其移动到名为 eg 的子目录processed中,然后从那里开始处理它。
  3. 完成后可选择删除它。

在任何健全的文件系统上,文件移动是原子的,只要它们发生在同一个文件系统/卷中。所以没有竞争条件。

多个接收器

如果处理可能需要比交付文件之间的时间更长的时间,您将建立一个积压,除非您有多个接收器进程。那么,如何处理多接收者的情况呢?

简单:每个接收器进程都像以前一样操作。关键是我们在处理文件processed 之前尝试将文件移动到该文件:而且相同文件系统文件移动的事实是原子的,这意味着即使多个接收者看到相同的文件completed并尝试移动它,也只有一个会成功。您需要做的就是确保检查 的返回值rename()或用于执行移动的任何操作系统调用,并且只有在成功时才继续处理。如果移动失败,其他接收者首先到达那里,所以只需返回并completed再次扫描目录。

于 2009-03-07T20:15:50.790 回答
1

如果操作系统支持,请使用文件系统挂钩来拦截打开和关闭文件操作。像大津子这样的东西。其他操作系统可能会以另一种方式让您了解文件操作,例如 Novell Open Enterprise Server 允许您定义 epoch,并读取在一个 epoch 期间修改的文件列表。

刚刚意识到在 Linux 中,您可以使用 inotify 子系统,或 inotify-tools 包中的实用程序

于 2009-03-09T09:02:58.533 回答
0

文件传输是系统集成的经典之一。我建议您获取Enterprise Integration Patterns这本书来构建您自己对这些问题的答案——在某种程度上,答案取决于您用于端点实现和文件传输的技术和平台。这是一个相当全面的可行模式集合,并且写得相当好。

于 2009-03-07T22:06:37.293 回答