我和我的同事创建了一些客户端服务器架构程序,它们使用增量来同步客户端与服务器。与删除记录有关的问题似乎出现在多个项目中。 服务器如何在本地删除记录并且仍然有足够的信息为 future 的客户端生成删除增量信息?
示例 1:
实时游戏使用 UDP 客户端-服务器在游戏之间同步实体。仅传输包含修改后的游戏状态和先前丢弃的数据包数据的增量。如果服务器删除了一个实体,它可以发送一个删除增量,告诉每个客户端删除该对象。这有效,除非数据包被丢弃。这对于正常状态数据是可以的,因为服务器可以识别哪些数据被丢弃并从中重新传输增量,但这意味着服务器无法在本地删除服务器实体(无需从每个客户端进行完整确认),因为没有数据将存在以从中生成删除增量。
示例 2:
客户端想要与存储在服务器上的数据库同步。服务器为服务器上的每条记录存储一个修改日期。当客户端请求同步时,它会传输它更新的最后日期。服务器收集自该日期以来已修改的所有记录,并将它们发送给客户端。仅当服务器保留已删除的每条记录并使用标志来指示删除时,这才适用于删除。服务器无法安全删除本地存储的记录。
在这两个示例中,我能想到的唯一解决方案是保留某种包含曾经删除过的所有内容的记录,或者在某个日期/时间后强制进行完整同步。这些看起来不像是可持续或优雅的模型。 有哪些可持续的方法可以解决此类问题?
最佳答案
为什么这看起来不可持续?许多同步框架都使用它,它被称为墓碑处理,afaik。该记录被删除或标记为已删除,并且在另一个表(如果涉及数据库)中保留对已删除项目的引用。这样系统就能够同步被删除的记录。事实上,这不仅仅是删除数据。有人可能会说记录的每次更新也是一次删除。因为旧版本的记录再也找不到了。因此,如果保留“旧”数据很重要,则不要向数据存储发送更新,而只发送插入。
在 UDP 和数据包丢失的情况下,您必须围绕它设计您的软件。如果游戏为某个已删除的实体提交数据,只需忽略它或正确响应它。这里有很多选择。
您可能还在研究事件溯源。它不是神圣的 grale 或任何东西,但它的工作方式与常规 CRUD 不同。相反,它使用 CQRS 来分离命令和查询端,事件源用于创建事件流。您只存储事件。因此,无论何时您想要声明某个实体,您都可以回读所有事件。它可能总是以插入、零次或多次更新开始,然后是一些删除语句。你将拥有你需要知道的一切。这些事件也会发送给创建最新状态读取模型的其他组件。这样,一些 UI 可以从读取模型中读取并且速度非常快,但是每个状态更改都来自事件流,处理每个事件的业务逻辑。
如果您对此感兴趣,请阅读 Greg Young 和许多其他人的 CQRS 和事件采购。
关于architecture - 如何在客户端服务器架构中为已删除的数据生成增量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18034791/