如何识别未同步的实体?客户是生成ID的人吗?

问题描述

假设我要同步(使用HTTP协议)名为Person的实体。因此,客户端(移动/桌面/任何)中的人员是服务器数据库中存在的人员的镜像副本。显然,服务器拥有所有人,而客户端仅拥有特定用户的人。

请考虑以下情况。

客户端离线。离线时,他创建一个Person,并且由于他无法连接到服务器,因此将其保留在本地存储中。比方说一个本地数据库sqlite或其他)。 这种情况发生的那一刻,应该如何识别这个人?

在我开始实现整个过程之前,我认为服务器应该是生成来找他的人的ID的服务器。但是,当我开始实施时,我开始面对这个问题。

在服务器生成ID的情况下,由于服务器永远不会看到此人,因此客户端必须给它提供一个ID,以便能够找到该人,并且显然使用此ID将其存储到其本地存储中。现在,当客户上线时,他会将人员发送到服务器。服务器,为其提供一个ID,并将其存储在自己的数据库中。此后,客户端将请求在上次同步后发生的任何人员更改,服务器将返回此特定人员。

举个例子。客户端处于脱机状态,创建100个人并将其存储到其本地存储中。人员1,人员2,​​人员3等...现在,他已连接到服务器,并发送了所有100个人。由于连接是通过HTTP进行的,因此客户端向post-persons端点发出了发布请求。然后,服务器生成ID(增量ID或UUID),并且可能还会更改其他一些属性。现在,客户访问get-persons端点,他看到100个更新的人员,每个人都有一个他不知道的新ID。 客户如何知道这些人中的哪些人对应于该客户已经拥有的人?删除旧客户的100个人,并插入100个带有服务器ID的新客户似乎是不合常规的。换句话说,客户端已知的Person 1在服务器中存储为Person [uuid],服务器将其返回为Person [uuid]。客户如何知道他的Person 1对应于Person [uuid]?一种解决方案可能是,将客户端的ID发送到服务器,服务器将像Person [uuid] 1那样响应。现在客户端知道,他的1是这个。在我看来,这似乎更加非传统。

第二个选项是让客户端生成UUID,无论它们离线还是在线。就我而言,这种解决方案似乎是“最简单”的方法。客户创建人[uuid]。当他联机时,他将其发送到服务器。在该客户端访问get-persons之后,他作为响应获得更新人[uuid]。他可以轻松地将其标识并存储在本地存储中。服务器不会为人员生成任何类型的ID。

我有什么想念的吗?到目前为止,我认为服务器是生成可同步实体ID的服务器,但我认为第二种方法更易于实现且更全面。但这会不会在以后引入任何“危险”?

对于要用于客户端或服务器的ID类型没有明确要求。但是,我知道在简单的增量编号上使用UUID进行权衡。

堆栈(即使我认为无关紧要):

  • 在Hibernate和MysqL中作为服务器的春季启动
  • 将Hibernate和H2独立作为本地存储的客户端
  • 一切Java 8

解决方法

还有其他可能的解决方案,最好的解决方案取决于您的具体情况-是否需要维护本地关系等。


第一个解决方案是在服务器上继续使用没有逻辑的ID。

根本不会生成ID并存储没有ID的人员(如果可能的话),并且在同步后,服务器会返回ID,然后您在本地更改ID。

因此,很容易知道哪些人已经与服务器同步(具有ID的人),哪些人尚未被服务器知道。

实现INSERT / UPDATE逻辑也很简单。

但是,如果您需要维护本地关系,则此解决方案可能会成为问题。

需要本地关系时,可以生成临时ID。假设您需要一个数字ID,因此所有正ID都是已经同步的,而负ID是临时的。

与服务器同步时,可以从服务器(正数)获得新的ID,然后只需重写本地数据库中的所有ID。但是,这有点容易出错,因为您必须确保更新所有关系。

您还可以具有localId和serverId。从技术上讲,您只需要serverId在全局范围内唯一即可在服务器上存储人员。您将serverId保留为空,并在实体与服务器同步后填充它(服务器返回它)。您可以根据需要生成localId并将其用于本地关系。但是,如果您需要同步多个客户端,并且每个客户端都想生成自己的本地ID,则这可能是一个有问题的方法。


第二种方法是使用ID池。它需要在服务器上进行一些工作并存储分配的池。

您可以为给定的客户端分配ID池。客户端必须至少在线一次,并且服务器发送其唯一的偏移量。

根据您的需要,您可以具有例如8字节的标识符(64位)。前36位可用于偏移量,因此您的服务器可以管理2 ^ 36个客户端。客户端可以免费使用最后28位。

因此,客户端只要需要新的ID并添加唯一偏移量=>即可获得内部唯一计数器,从而获得全局唯一标识符。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...