我有一个包含大约10种对象的应用程序。每种类型可能有几千个对象实例。这些对象列表需要在不同计算机上运行的应用程序之间保持同步。如果添加,更改或删除了某个对象,则需要将其传播到其他计算机。
这将是一个星形拓扑 - 有一个中央主人,其余的是客户。
我有会话的概念,因此可以存储有关每个客户端的数据。
这是否有一个好的设计模式?更好的是,是否有一个(基于模板的?)库可以处理容器,询问容器自客户端X到来后发生了哪些变化并将该delta发送出去?
现在我认为每个对象类型的容器都有一个更新计数器。添加/更改/删除某些内容时,更新计数器会递增,并且更改的对象将使用该值进行标记。每个客户端在获得更新时都会保存更新计数器的值。之后它将返回并要求任何更改,因为它是更新计数器值。最后,删除被保存为墓碑记录(虽然我不确定何时清除它们。)
让事情变得更难的一件事是客户可以在没有中央服务器必须知道的情况下来来往往,虽然我猜可能存在超时概念(如果服务器在5分钟内没有从客户端收到消息,它会假设客户端已经不见了)
这是一个众所周知的模式吗?还有其他建议吗?
答案 0 :(得分:1)
如何实现同步非常取决于您的需求。是否需要将更改发送到客户端,或者客户端在使用对象时检查对象是否是最新的是否足够?如何使用Proxy pattern?此模式允许您创建对象的代理实现,可以检查它们是否是最新的,如果不是,则进行更新,然后返回结果。我会通过在主服务器上的对象上设置lastChanged时间戳并在客户端对象上设置lastUpdated时间戳来实现此目的。如果延迟是一个问题,检查每个调用对象是否是最新的可能不是一个好主意。考虑使用一个单独的线程来查询master以查找更改的对象,并将它们标记为“脏”。这也可以大大减少网络流量。
答案 1 :(得分:0)
可能很容易实现并且仍然非常高效的选项是将对象堆处理为不透明的blob并使用librsync来同步它们。听起来所有更新都是从主服务器到客户端的一个方向,并且可能存在客户端上对象的持久表示 - 文件或其他内容。我假设它是本答案其余部分的文件,但可以使用任何字节序列。
它的工作方式是每个客户端都会生成其blob本地副本的librsync“签名”,并将该签名发送给主服务器。签名大约是blob大小的1%。然后,master将使用librsync计算该签名与当前数据之间的增量,并将增量发送到客户端,客户端将使用librsync将增量应用于其blob的本地副本。
librsync API很简单,签名/增量数据传输相对有效。
如果这不可行,那么采用更加手动的“基于delta”的方法可能仍然有用,以避免必须进行每个对象的版本控制。每次主人做出改变时,都应该将该更改记录到日志中,记录所做的事情和对象。版本控制在整个数据库级别完成,因此实际上会为每个日记帐分录分配版本号。
当客户端连接时,它应该发送整个对象集合的版本,然后服务器可以使用客户端版本和最新条目之间的日志内容进行响应。如果通过完全替换对象内容来完成给定对象的更新,则可以通过过滤除每个对象的最新版本之外的所有对象来优化它。如果主服务器还跟踪它发送到哪个客户端的版本,它可以知道何时丢弃旧日记帐条目是安全的。即使它没有跟踪,你仍然可以根据一些启发式(可能只是年龄)丢弃旧的日记条目,如果你从最后版本比你最早的日记条目更早的客户端收到连接,那么你只需要将整个对象集发送到该客户端。