如果您对远程系统只有黑盒访问(例如 NFS 协议),那么您没有太多选择,除非该协议支持您的需求。所以我假设你可以控制远程系统。
“简单”的方法是在每台计算机上运行本地 inotify/fanotify 侦听器,以通过网络转发通知。 FAM can do this over NFS.
所有基于通知的系统的一个问题是在各种边缘情况下丢失通知的风险。这在网络上变得更加尖锐 - 例如。客户端确认收到通知,然后立即崩溃。您可以建立可靠的消息队列,但恕我直言,这种方式很疯狂......
更明智的方法是基于无状态哈希的扫描。
我喜欢将以下设计称为“hnotify”,但这不是一个既定术语。这些想法被许多版本控制和备份系统广泛使用,可以追溯到Plan 9。
核心思想是,如果您知道文件的加密哈希,您可以组成一个表示文件目录的单个哈希 - 如果 any 文件更改,它会更改 - 您可以构建这些底部-up 表示整个文件系统的状态。
(Git stores things this way 效率很高。)
为什么哈希树很酷?如果你有两棵哈希树——一个代表你在过去看到的文件系统状态,一个代表当前状态——你可以很容易地找出它们之间的变化:
- 你从根源开始。如果它们不同,则读取 2 个根目录并比较子目录的哈希值。
- 如果子目录在两棵树中具有相同的哈希值,则其下的 nothing 会发生变化。没必要去那里。
- 如果子目录的哈希值发生变化,则递归比较其内容 — 调用步骤 (1)。
- 如果一个有子目录而另一个没有,那是一种变化。使用一些全局表,您还可以检测移动/重命名。
请注意,如果更改的文件很少,您只能读取当前状态的一小部分。因此,远程系统不必向您发送整个哈希树,它可以是“给我这个目录的哈希;现在好了……”的交互式乒乓球。
(这类似于 Git 的愚蠢 http 协议 worked; there is a newer 协议,往返次数更少。)
这与轮询整个文件系统的更改一样健壮且防错误——你不会错过任何东西——但相当有效!
但是服务器如何跟踪当前的哈希值?
不幸的是,对大多数人来说,完全散列所有磁盘写入的成本太高了。如果您幸运地运行重复数据删除文件系统,您可能会免费获得 if,例如ZFS 或 Btrfs。
否则,您将不得不重新读取所有更改的文件(这比在文件系统层执行此操作更昂贵)或使用 假文件哈希:对文件进行任何更改时,发明一个新的随机“散列”使其无效(并尝试在移动中保留假散列)。仍然计算树上的真实哈希值。现在你可能会有误报——当内容相同时你会“检测到变化”——但绝不会出现误报。
无论如何,关键是无论你做什么有状态的 hack(例如,确保定期扫描 inotify),你只能在服务器上本地进行。在整个网络中,您只发送代表当前状态(或其子树)快照的哈希值!这样一来,您就可以拥有一个包含许多服务器和客户端、间歇性连接的分布式系统,并且仍然保持理智。
附: Btrfs 可以efficiently find differences from an older snapshot。但这是在服务器上拍摄的快照(并导致所有数据都被保留!),不如客户端轻量级哈希树灵活。
附:您的标签之一是 HadoopFS。我不太熟悉它,但我怀疑它的很多文件都是一次写入后不可变的,它可能能够原生地为您提供某种可以用作假哈希的文件/块 ID?
现有工具
-
我想到的第一个工具是bup index。 bup 是一个非常聪明的基于 git 的重复数据删除备份工具(仅可扩展到海量数据),因此它位于上述基础之上。理论上,在服务器上索引 bup 中的数据并通过网络执行 git fetch 甚至可以实现我上面描述的新内容的哈希遍历比较——不幸的是,bup 生成的 git 存储库太大,git 本身无法应付.此外,您可能不希望 bup 读取和存储您的所有数据。但是bup index 是一个单独的子系统,它可以快速扫描文件系统以查找潜在更改,而无需读取更改的文件。
目前 bup 不使用 inotify,但它一直是 discussed in depth。
哦,bup 使用 Bloom 过滤器,这是一种近乎最佳的方式来表示具有误报的集合。我几乎可以肯定 Bloom 过滤器在优化无状态通知协议中发挥作用(“这是我所有的压缩位图;你应该能够用它来缩小查询范围”或“这是我的压缩位图希望收到有关“的通知”)。不确定the way bup uses them 是否对您直接有用,但这个数据结构绝对应该在您的工具带中。
另一个工具是git annex。它也基于 Git(你注意到趋势了吗?),但旨在将数据本身排除在 Git 存储库之外(所以 git fetch 应该可以正常工作!)并且有一个 "WORM" option 使用假哈希以获得更快的性能。
替代设计:压缩可重播日志
我曾经认为以上是客户检查更改内容的唯一理智的无状态方法。但我刚刚阅读了http://arstechnica.com/apple/2007/10/mac-os-x-10-5/7/ 关于 OS X 的 FSEvents 框架的信息,它的设计可能更简单:
- 所有更改都记录到文件中。它会永久保存。
- 客户可以要求“为我重播自事件 51348 以来的所有内容”。
- 神奇之处在于日志的粒度很粗(“此目录中的某些内容发生了变化,去重新扫描看看”,将 30 秒内的重复更改合并在一起),因此该日志文件非常紧凑。
在低级别,您可能会采用类似的技术——例如哈希——但顶层接口不同:你处理的是事件时间线,而不是快照。它可能更适合某些应用程序。