客户端 - 服务器数据同步策略[Java]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了客户端 - 服务器数据同步策略[Java]相关的知识,希望对你有一定的参考价值。
我有一个与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个客户端。)
现在,是否有一种模式或最着名的做法来处理这样的问题?
我会考虑以下想法:
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。
只要您跟踪在服务器上创建给定项目的时间(这可能是您出于其他原因已经完成的事情),您始终可以知道客户端是否首先调用包含在结果集中的给定项目。如果这对您有意义,同样适用于删除项目。
诀窍是跟踪您开始提供第一个请求的时间点,从那时起,您可以通过将时间戳与创建/删除时间戳对应来轻松查看是否已更改该集。您当然可以决定现在确实要通知客户创建新项目(因此它将在特定时间点获得与服务器状态一致的结果)。通过使响应数据集更复杂,您还可以提醒客户端,如果在您的情况下这是有意义的,那么它已经删除了“它旁边”的一个或多个对象。
警告:
虽然这应该为所述问题提供可行的解决方案,但请记住,实际实施必须考虑到由于订购而产生的问题。您必须根据您的情况决定是否必须进行管理:如果确实存在问题,则返回组结构(以及客户端解释)将变得更加复杂。
问题如下:在大多数情况下,结果集(尽管是“分页”)将具有一些固有的顺序:它可以是“按价格,按升序”或其他任何内容,具体取决于上下文。如果确实如此,那么现在有一个全新的问题要处理:
- 如果在客户端/服务器对话期间创建新对象,则无法保证新对象不应成为已传递给客户端的部分答案的一部分(除非您的“订购条件”类似于“创建”时间戳“)。
- 如果在客户端/服务器交换期间可能发生删除,则情况会更糟,因为如果已删除已传递到客户端的对象,则通知将更加复杂。
除非它确实是一个严格的要求,否则我会选择API根据第一次调用的时间戳返回一致的快照。
一个简单的策略:
步骤1检索要更新的项目列表
步骤2将该列表传输给客户端
步骤3将请求拆分为块(每页1000个条目)并逐页查询
步骤4在客户端上的条目上设置时间戳,例如justupdated = now()
步骤5检索要更新的项目列表,并减去刚刚更新的所有条目
步骤6直到有空集,重复步骤3
步骤7当delta为0时,您的更新已完成。
或者:
步骤1评估客户端上的所有过期条目(早于x)
步骤2查询来自客户端的所有过期条目的逐页更新,并设置更新时间戳
第3步询问服务器更新
步骤4查询页面并在客户端设置更新时间戳
步骤5询问服务器是否有更新
步骤6使用已更新的条目计算增量。直到delta = 0页面检索数据并设置时间戳。并重复步骤5
如果您保存了包含客户端上收到的所有项目的散列值的列表,并且每次都通过请求将其发送到服务器,该怎么办?
- 服务器将为列表中的每个项目(或DB,无论您使用什么)保存哈希值,因此当它收到请求时,它会将它具有的项目与从客户端获得的哈希项目列表进行比较。
- 服务器只发送它从客户端获得的列表中不包含的前10个项目(意味着客户端直到现在才看到它们)。
- 每次服务器删除项目(或以预定的时间间隔),它将通知每个发送请求的客户端(也通过哈希列表),因此客户端也可以清空其列表,从而避免臃肿名单。
以上是关于客户端 - 服务器数据同步策略[Java]的主要内容,如果未能解决你的问题,请参考以下文章
在域控制器上设置NTP时间自动同步的组策略,使域中所有客户机的时间保持一致