客户端 - 服务器数据同步策略[Java]

时间:2014-10-14 11:05:57

标签: java algorithm design-patterns synchronization

我有一个与Rest WebService通信的应用程序。我们希望实现一种策略,其中App将首先询问第一个X数量的项目,并且一旦它们全部使用它们,将要求下一个X.我的问题是关于在该实现中实现的最佳实践/模型/算法服务器来解决这个规范。

我们的方法A

  • 服务器知道它总共有Z项(比如100)
  • 每次应用程序请求新项目时,它都会通知服务器它之前执行了多少时间。像URL / givemedata / 1或URL / givemedata / 6之类的东西。在第一个请求中,服务器将在db上发送前10个项目,在seconde示例中,服务器将发送50到60个项目。

问题:         如果我们在服务器上插入新数据怎么办?如果我们从服务器删除数据怎么办?如果在第一个请求发出时服务器有100个项目,它会将前10个项目发送到应用程序。但是,如果在第二次请求时服务器有300项,我们保持相同的逻辑(总数的10%),服务器将从30到60返回应用程序项目。不仅我们不会发送20项如果我们从服务器上删除了一些项目,我们将来可能会发送重复的项目。

我们的方法B

  • 保存我们发送给每个客户的每件商品。

问题:这就是我喜欢称之为懒惰的选择。因为它很容易保存我们发送给每个客户端的内容,然后只是将我们已发送的请求排除在未来的请求之外,但就性能而言,这可能是一个大问题(想象一下,如果我们有10000个项目和20000个客户端。)

现在,是否有一种模式或最着名的做法来处理这样的问题?

3 个答案:

答案 0 :(得分:2)

我有以下想法:

a)服务器在客户端第一次调用时知道它总共有Z项(比如100)。这是通过将客户端ID作为密钥保存在哈希表中的服务器端时间戳来处理的。

b)每当应用程序要求新项目时,它将返回一组 N (比方说10个)项目作为集合/数组/其他 - 加上一个数字通知客户端如何许多物品尚未归还。

示例:( 100项,每次10项)

  • 客户#34呼叫服务器{它的20141023-10:04:34服务器)
  • 服务器在其内部状态结构中保存#34,20141023-10:04:34。
  • 服务器返回:((ax,bc,rr,tt,yd,ty,ae,t4,t2,a2),90)即一组 10个元素,以及另外90个等待的通知。
  • 客户#34呼叫服务器(再次{它的20141023-10:05:11为 服务器))服务器返回((vx,gf,gg,yu,td,fr,we,aq,ee,lp),80)即a 一组10个元素,以及另外80个等待的通知。
  • 有人创造了项目" u7"在服务器上,时间{它的20141023-10:05:12 对于服务器)
  • 客户#34呼叫服务器(再次{它的20141023-10:05:58为 服务器))服务器返回:((zx,gk,ig,tg,ed,rz,wt,a5,1e,wj),71) 即一组10个元素,以及另一个71的通知 正在等待......因为它知道自那以后就创建了一个新项目 已收到原始请求。

最后,当服务器返回最后一项时,所以:

  • 客户端#34呼叫服务器(这是第11次呼叫,因为在会话期间已经创建了其他一些内容{它是服务器的20141023-10:09:25))
  • 服务器返回:((zq,g1,i3,t7,e7,r9,sa,ax,1x,k6),0)并从其表中删除#34。

只要您跟踪在服务器上创建给定项目的时间(这可能是您出于其他原因已经完成的事情),您始终可以知道客户端是否首先调用包含在结果中的给定项目组。 同样适用于删除项目,如果这对您有意义的话。

诀窍是跟踪您开始提供第一个请求的时间点,从那时起,您可以通过将时间戳与创建/删除时间戳对峙来轻松查看是否已更改该集。 您当然可以决定现在确实要通知客户创建新项目(因此它将在特定时间点获得与服务器状态一致的结果)。 通过使响应数据集稍微复杂一些,您还可以向客户端发出一个或多个对象的警告,即它的侧面"已被删除,如果这在你的情况下是有道理的。


<强>警告:

虽然这应该为所述问题提供可行的解决方案,但请记住,实际的实施必须考虑到由于订购而导致的问题。你必须决定是否必须管理它,具体取决于你的情况:如果它确实是一个问题,那么returnset结构(以及Client解释)将变得更加复杂。

问题如下:在大多数情况下,结果集(虽然&#34;分页&#34;)将具有一些固有的顺序:它可能是&#34;按价格,上升&#34;或其他任何东西,取决于具体情况。如果情况确实如此,那么您现在需要处理一个全新的问题:

  • 如果在客户端/服务器对话期间创建新对象,则无法保证您的新对象不应成为您已交付给客户端的部分答案的一部分(除非您的&#34;订购标准&#34;类似于&#34;创建时间戳&#34;)。
  • 如果在客户端/服务器交换期间可能发生删除,情况会更糟,因为如果已删除已传送到客户端的对象,则通知将更加复杂。

除非确实是严格要求,否则我选择让API根据第一次通话的时间戳返回一致的快照。

答案 1 :(得分:1)

一个简单的策略:

第1步检索要更新的项目列表

第2步将该列表传输到客户端

第3步将请求拆分为块(每页1000个条目)并逐页查询

第4步在客户端上的条目上设置时间戳,例如 justupdated = now()

第5步检索要更新的项目列表并减去刚刚更新的所有条目

第6步在有空集之前,请从第3步重复

步骤7 当delta为0时。您的更新已完成。

可替换地:

第1步评估客户端上的所有过期条目(早于 x

第2步查询来自客户端的所有过期条目的逐页更新并设置更新时间戳

第3步向服务器询问更新

第4步逐页查询并在客户端设置更新时间戳

第5步向服务器询问更新

第6步使用已更新的entires计算增量。直到delta = 0逐页检索数据并设置时间戳。并重复第5步

答案 2 :(得分:0)

如果您保存了包含客户端上收到的所有项目的散列值的列表,并且每次都通过请求将其发送到服务器,该怎么办?

  1. 服务器会为列表中的每个项目(或DB,无论你使用什么)保存哈希值,因此当它收到请求时,它会将它拥有的项目与收到的散列项目列表进行比较来自客户。

  2. 服务器只发送前10个从客户端获取的列表中的项目(意味着客户端直到现在才看到它们)。

  3. 每次服务器删除项目(或以预定的时间间隔)时,它都会通知每个发送请求的客户端已删除这些项目(也通过哈希列表),因此客户端可以清空其列表同时避免臃肿的名单。