如何在客户端服务器体系结构中为已删除的数据生成增量?

Jus*_*ers 5 language-agnostic architecture synchronization client-server

我和我的同事已经创建了一些客户端服务器体系结构程序,这些程序使用增量来将客户端与服务器同步.与删除记录有关的问题似乎出现在多个项目中.服务器如何在本地删除记录,仍然有足够的信息为未来的客户端生成删除增量信息?

例1:

实时游戏使用UDP客户端 - 服务器在游戏之间同步实体.仅发送包含修改的游戏状态和先前丢弃的分组数据的增量.如果服务器删除实体,它可以发送删除增量,告诉每个客户端删除该对象.除非丢弃数据包,否则此方法有效.这对于正常状态数据是可以的,因为服务器可以识别丢弃了哪些数据并从中重新传输增量,但这意味着服务器无法在本地删除服务器实体(没有从每个客户端进行完全确认),因为没有将存在数据以生成删除增量.

例2:

客户端希望与存储在服务器上的数据库同步.服务器为服务器上的每条记录存储修改日期.当客户端请求同步时,它会传输更新的最后日期.服务器收集自该日期以来已修改的所有记录,并将它们发送到客户端.仅当服务器保持每条记录都被删除并使用标志表示删除时,才能使用删除操作.服务器无法安全删除本地存储的记录.

在这两个示例中,我能想到的唯一解决方案是保留包含所有已删除内容的某种记录,或者在某个日期/时间之后强制执行完整同步.这些似乎不是可持续或优雅的模型.有哪些可持续的方法可以解决这类问题?

Den*_*elt 1

为什么这看起来不可持续?很多同步框架都使用这个,它被称为墓碑,据我所知。该记录被删除或标记为已删除,并且在另一个表(如果涉及数据库)中保存对已删除项目的引用。这样系统就能够同步已删除的记录。事实上,这不仅仅是删除数据。有人可能会说,记录的每次更新也是删除。因为旧版本的记录再也找不到了。因此,如果保留“旧”数据很重要,则只发送插入,而不是向数据存储发送更新。

如果出现 UDP 和数据包丢失,您必须围绕它设计软件。如果游戏提交了某个已删除实体的数据,只需忽略它或对其做出正确响应即可。这里有很多选择。

您可能还会关注事件溯源。它不是什么神圣的东西,但它的工作方式与普通的 CRUD 不同。相反,它使用 CQRS 来分离命令和查询端,并使用事件源来创建事件流。您只存储事件。因此,每当您想要声明某个实体时,您都会读回所有事件。它可能总是以插入、零次或多次更新以及一些删除语句开始。里面有你需要知道的一切。这些事件也会发送到创建最新状态的读取模型的其他组件。这样,某些 UI 可以从读取模型中读取数据并且速度极快,但每个状态更改都通过事件流进行,处理每个事件的业务逻辑。

如果您对此感兴趣,请阅读 Greg Young 和许多其他人关于 CQRS 和事件溯源的内容。