文档服务器:处理并发保存
我正在实现文档服务器。当前,如果两个用户打开同一文档,然后对其进行修改并保存更改,则该文档的状态将是不确定的(第一个用户的更改将永久保存,第二个用户的更改将永久保存)。这是完全不能令人满意的。我考虑了解决此问题的两种可能性:
第一种是在某人第一次打开文档时将其锁定,而在关闭时将其解锁。但是,如果到服务器的网络连接突然中断,则文档将保持永久锁定状态。显而易见的解决方案是将常规ping发送到服务器。如果服务器连续未从特定客户端收到K个ping(K> 1),则该客户端锁定的文档将被解锁。如果该客户端重新出现,则文档将再次锁定(如果有人尚未将其锁定)。如果客户端应用程序(在Web浏览器中运行)意外终止,这也可能会有所帮助,从而无法向服务器发送"退出,解锁我的文档"信号。
第二种是存储由不同用户保存的同一文档的多个版本。如果快速连续更改文档,系统将提供合并版本或者选择首选版本。为了优化存储空间,仅应保留文档差异(就像源代码控制软件一样)。
考虑到与服务器的连接有时可能很慢且无响应,我应该选择哪种方法?应该如何确定参数(ping间隔,快速连续间隔)?
P.S.不幸的是,我无法将文档存储在数据库中。
解决方案
回答
我的建议将是第一个。当第一个用户(Bob)打开文档时,他获得了一个锁,因此其他用户只能读取当前文档。如果用户在使用文档时保存该文档,则他将保持锁定状态。只有当他退出文档时,该文档才会被解锁,其他人可以对其进行编辑。
如果第二个用户(Kate)在Bob锁定文件的同时打开了该文件,Kate将收到一条消息,指出该文件不可编辑,但她可以阅读该文件,直到释放了锁定为止。
因此,当鲍勃获得锁时,可能会保存文档一次或者两次,然后退出应用程序而使锁挂起,那会发生什么呢?
就像我们自己说的那样,要求带锁的客户端以一定频率发送ping可能是最好的选择。如果我们在一定时间内没有收到客户端的ping命令,这实际上意味着他的客户端不再响应。如果这是一个Web应用程序,则可以使用javascript进行ping。上次保存的文档将释放其锁定,Kate现在可以获取它。
查验可以包含客户端已锁定的文档的名称,服务器可以计算何时收到该文档的最后查验。
回答
我们描述的第一个选项本质上是悲观锁定模型,而第二个是乐观模型。
真正选择哪一个取决于许多因素,但本质上归结为企业希望如何运作。例如,如果他们需要编辑的文档被另一个用户锁定了,会给用户带来不便吗?如果文档被锁定并且某人在与客户连接的情况下去度假,会发生什么情况?每个文档可能发生的争用是什么,即两个用户同时修改同一文档的可能性有多大?单个文档中的修改可能有多本地化? (如果定期修改同一节,则执行合并可能比重新进行更改要花费更长的时间)。
假设竞争相对较低和/或者每个更改的大小都很小,那么我可能会选择一个乐观的模型,该模型使用自动或者手动合并来解决冲突。文档内容的版本号或者校验和可用于确定是否需要合并。
回答
当前,文档是由少数人发布的,每个人都在一个单独的主题上工作。因此,锁带来的不便最小化。
人们大多会扩展现有文档并纠正其中的错误。
说到悲观模型,可以通过将锁定过期日期设置为(例如)锁定开始日期的前一天来避免"左客户端连接N天"的情况。因为编辑的文档绝不是关键任务,并且很少有多个用户对其进行修改,所以就足够了。
现在考虑乐观模型。如果文档具有某种常规(例如,层次结构)结构,应如何检测差异?如果不?在这些情况下成功进行自动合并的机会是什么?
这种情况变得更加复杂,因为某些文档(由" admins"用户组编辑)包含重要的配置信息(文档全局索引,用户角色等)。在我看来,锁对于这种信息更有利,因为它不会每天更改。因此,某些混合解决方案可能是可以接受的。
你怎么认为?