0

我有一个包含大约 10 种对象的应用程序。每种类型都可能有几千个对象实例。这些对象列表需要在不同机器上运行的应用程序之间保持同步。如果添加、更改或删除对象,则需要传播到其他机器。

这将是一个星型拓扑——有一个中央主机,其余的是客户端。

我确实有会话的概念,因此可以存储有关每个客户端的数据。

是否有一个好的设计模式可以遵循?更好的是,是否有一个(基于模板的?)库可以处理询问容器自客户端 X 出现以来发生了什么变化并让该增量发送出去?

现在我在想每个对象类型的容器都有一个更新计数器。当添加/更改/删除某些内容时,更新计数器会增加,并且更改的对象会被标记为该值。每个客户端在获得更新时都会保存更新计数器的值。稍后它会回来并要求任何更改,因为它是更新计数器值。最后,删除被保存为墓碑记录(尽管我不确定何时清除它们)。

使这更难的一件事是客户端可以在中央服务器不一定知道的情况下进出,尽管我猜可能存在超时概念(如果服务器在 5 分钟内没有收到客户端的消息,则假定客户端已消失)

这是众所周知的模式吗?有什么额外的建议吗?

4

2 回答 2

1

如何实现同步很大程度上取决于您的需求。是否需要将更改发送给客户端,或者客户端在使用对象时检查对象是否是最新的就足够了?如何使用代理模式?此模式允许您创建对象的代理实现,可以检查它们是否是最新的,如果不是,则进行更新,然后返回结果。我会通过在主对象上使用 lastChanged 时间戳和在客户端对象上使用 lastUpdated 时间戳来做到这一点。如果延迟是一个问题,则在每次调用时检查对象是否是最新的可能不是一个好主意。考虑有一个单独的线程来查询主服务器以查找更改的对象并将它们标记为“脏”。这也可以显着减少网络流量。

您还可以查看观察者模式Publish/Subscribe

于 2009-09-18T15:13:53.137 回答
0

一个可能很容易实现并且仍然非常有效的选项是将一堆对象视为不透明的 blob 并使用 librsync 来同步它们。听起来所有更新都流向一个方向,从主服务器到客户端,并且客户端上的对象可能存在一些持久表示——文件或其他东西。我假设它是这个答案其余部分的文件,尽管可以使用任何字节序列。

它的工作方式是每个客户端都会为其本地 blob 副本生成一个 librsync“签名”,并将该签名发送给主服务器。签名约为 blob 大小的 1%。然后,主服务器将使用 librsync 计算该签名和当前数据之间的增量,并将增量发送到客户端,客户端将使用 librsync 将增量应用到其本地 blob 副本。

librsync API 简单,签名/增量数据传输相对高效。

如果这不可行,采用更手动的“基于增量”的方法可能仍然有用,以避免必须进行每个对象的版本控制。每次 master 进行更改时,它应该将该更改记录到日志中,记录所做的事情和对象。版本控制是在整个数据库级别完成的,因此实际上为每个日记帐分录分配了一个版本号。

当客户端连接时,它应该发送它的整个对象集合的版本,然后服务器可以响应客户端版本和最新条目之间的日志内容。如果对给定对象的更新是通过完全替换对象内容来完成的,那么您可以通过过滤掉每个对象的最新版本以外的所有内容来优化它。如果主服务器还跟踪它已发送给哪个客户端的版本,它就可以知道何时可以安全地丢弃旧的日志条目。即使它没有跟踪,您仍然可以根据一些启发式(可能只是年龄)丢弃旧的日记条目,如果您收到来自最新版本比您最旧的日记条目旧的客户端的连接,那么您只需要将整个对象集发送到该客户端。

于 2009-10-16T14:37:19.817 回答