在实时编辑器数据上使用 Rails 乐观锁定

Using Rails optimistic locking on real-time editor data

我在 Rails 应用程序中使用实时编辑器 (https://beefree.io/)。多个用户可以编辑一个文档,它每 10 秒自动保存一次,返回一个代表该文档的 JSON 对象以及一个随着每次更改而递增的版本号。 JSON 对象正在保存到与文档模型关联的 table。

我很好奇是否可以使用乐观锁定来防止用户的旧更改在保存请求未及时完成的​​情况下覆盖新更改。这个想法是使用编辑器提供的版本号,并在 lock_version 列中使用它。我可以像那样将任意值传递给 lock_version 吗?或者数据库是为了增加值本身?

我遇到的另一个问题是,我正在保存到 table,其中包含我不想被此 lock_version 属性锁定的其他列。可以专门锁定实时数据栏吗?

I'm curious if optimistic locking could be used to prevent user's old changes from overwriting newer changes in the case that a save request doesn't complete in time. The idea would be to use the version number that the editor provides, and use it within the lock_version column. Can I pass an arbitrary value to lock_version like that? Or is the database meant to increment the value itself?

使用 Rails' 内置的乐观锁定,Active Record(而不是您的代码)应该负责递增 lock_version。您也许可以通过更新传递自己的 lock_version,但 Rails 仍会随着对模型的任何其他更新自动递增它。但是,考虑到你问题的第二部分......

Another issue I have is that I'm saving to a table that has other columns that I don't want to be locked by this lock_version attribute. Can I specifically lock the real-time data column?

仅针对某些列的更新锁定不是 Rails 当前支持的功能,尽管可能有 gem 或猴子补丁可以实现。但是,考虑到这一点以及您对自定义版本号的需求,最简单的方法可能是仅针对此更新自己实施乐观锁定:

# last version is what the editor thinks is the last saved version
# new version is the new version provided by the editor
# this update will only succeed if the document still has version=last_version

Document.where(id: document.id, version: last_version)
        .update_all(version: new_version, text: new_text)

我确实想指出,虽然这可以防止乱序更改,但协作编辑(两个或更多人实时编辑同一个文档)仍然无法完全发挥作用。要获得真正的协作编辑器,您需要基于 OT (operational transform) or CRDT (conflict-free replicated data type) 中的任何一个实施解决方案。另见: