OT算法在协同编辑中的应用

数字先锋
• 阅读 7473

1 背景

疫情的原因推进了在线面试的应用场景,除了音视频通话技术,对于IT行业的面试,必不可少的要写写代码,所以其中一项重要功能是协同编辑,下面就让来分析一下协同编辑功能的实现方案和OT算法的应用。

2 协同编辑场景

协同编辑的场景是在同一房间内,所有人都可同时操作编辑器内容,关键是让所有人看到的内容是一致的,这里面涉及的技术就包括了web编辑器,消息的广播和保证内容一致的算法,我们今天讨论的是保证内容一致的算法。

让我们看下实现保证内容一致的一些思路:

  • 思路1: 全量覆盖
    这种方法就是简单粗暴,每次都把编辑器的内容全量广播给其他人,这样在多人同时操作的时候就会有相互覆盖的现象,导致无法同时编辑,所以是不可取的。
  • 思路2: 加操作锁
    既然同时编辑会有相互覆盖的问题,那就加个操作锁,每次改变之前之前先抢一下锁,然后再改变,这种思路不是实现同时编辑,而是强制不同时编辑,会导致体验很差,明明输入了但是因为没有抢到锁而不生效。
  • 思路3: 增量操作
    既然全量传递会相互覆盖,那就增量的传递,只传递这次改变了什么,比如我在第2个字符插入了'xx'等等,这样虽然不会全量覆盖了 但是同时操作会导致内容不一致,举例如下图:

OT算法在协同编辑中的应用

两个用户,开始的内容都是AAAZ,同时操作,经过传递和转换之后两端的内容就不一致了。
OT协同算法的核心就是解决该问题。

3 OT算法

OT算法的关键技术点总结为四点:定义原子操作、版本确认机制、操作转换、客户端状态转移,下面就分别讲解。

3.1 定义原子操作

OT算法中对于内容的操作抽象为三种:

  • Retain 保持操作,用大于0的数字表示 记录要保持的字符数量
  • Insert 插入操作,用插入的字符串表示
  • Delete 删除操作,用小于0的数字表示 -n就是删除n个字符

每次对于整个文本的处理都可以用一个有上述3中原子操作的数组表示。下面我举一些直观的例子。

  • "" -> "A" ,操作数组为 ["A"] 只有一个Insert
  • "A" -> "AB" ,操作数组为 [1,"B"] 保持一个字符,然后插入B
  • "ABC" -> "AB" ,操作数组为 [1,-1,1] 保持一个字符,删除一个字符,然后再保持一个字符

编辑器和服务端之间传输的就是这种操作数组,当收到之后会将其转换为操作对象,定义如下:

function TextOperation () {
    this.ops = [];
    this.baseLength = 0;
    this.targetLength = 0;
  }

其中除了 this.ops记录操作数组之外,还增加了两个属性this.baseLengththis.targetLength

  • this.baseLength表示该操作前文本的长度,会用于操作转换时的校验。
  • this.targetLength表示该操作应用在文本后,文本的长度。

举个复杂的例子:

  • "123456789" -> "123A89" ,操作数组为 [3,"A",-4,2],转成的操作对象为

    {
    ops: [3,"A",-4,2],
    baseLength: 9,
    targetLength: 6
    }

3.2 版本确认机制

在OT协同算法中,服务端作为一个记录文档内容和所有历史版本操作的中心,当有新的客户端建立连接时首先进行一次同步,之后客户端每次发送一个操作时 还要同时发送本次操作时基于什么版本进行的更新,这样服务端会从该版本开始进行操作转换。客户端每次的操作不能直接修改当前的版本,而是要收到服务端的确认之后才能进行版本的更新,因为客户端不记录所有历史的操作和版本的对应关系,通过未确认的状态来判断是否需要操作转换。举例如下图:
OT算法在协同编辑中的应用

3.3 操作转换

操作转换是OT算法的核心,它的核心公式是:

[A`,B`]  = transform(A,B)
    
apply(apply(S, A), B') = apply(apply(S, B), A')

AB两个操作,经过转换之后生成A`和B`, 使得对于相同的内容S 经过A和B`的应用结果 等于 经过B和A`的应用结果,具体transform代码参见开源项目:ot.js

这里有一个菱形表示法用于图形化的描述OT的操作转换过程:
OT算法在协同编辑中的应用
我们可以这样理解,每一个点是一个状态,每一条边是一个操作,左边的永远是客户端的操作,
右边的永远是服务端的操作,两者在相同的状态下,客户端经过A和B`之后和服务端经过B和A`之后达到相同的状态。 这是最基本的一个版本冲突的菱形表示法,实际应用中会有更多的版本冲突,使用菱形表示法会把整个过程展示的很直观。

3.4 客户端状态转移

客户端每次操作不会立刻增加版本,而是要等待服务端的确认后增加版本,同时客户端的操作在没有被服务端确认之前,是不会继续发送新的操作,而是将要发送的操作进行缓存,等待确认后再进行发送,这里客户端就维护了三种状态,除了客户端的发送之外,还可能从服务端接受操作,不通的状态客户端会有不同的处理。

  • Synchronized, 已经同步状态,客户端没有待确认的操作。
  • AwaitingConfirm, 等待确认状态,客户端有等待服务端确认的操作。
  • AwaitingWithBuffer,等待确认状态,并且还有待发送的操作。

三种状态的转移如下图所示:
OT算法在协同编辑中的应用

4 OT场景分析

以上讲解了OT算法的关键技术,下面就针对需要进行OT操作的场景进行分析。

4.1 客户端修改一次,服务端修改一次冲突

此时客户端的状态是AwaitingConfirm,而收到了服务端下发的操作,菱形表示法如下:
OT算法在协同编辑中的应用
解释:客户端进行了A操作,服务端先进行了B操作,客户端进行OT之后 应用B`,等待的状态变为
A`, 而服务端收到A之后,同样与B进行OT,然后应用A`。

4.2 客户端修改一次,服务端修改多次冲突

此时客户端的状态是AwaitingConfirm,相比于4.1的情况,在收到修改确认之前,连续多次收到服务端的下发,菱形表示法如下:
OT算法在协同编辑中的应用
客户端先后 应用B1`和B2`,可以接受更多的修改。

对于服务端来说,当收到客户端的操作A时,是连续进行转换,菱形表示法如下:
OT算法在协同编辑中的应用
让操作A连续的和操作B1和B2进行转换,最终应用A``。

4.3 客户端修改多次,服务端修改一次冲突

此时客户端的状态是AwaitingWithBuffer,客户端变化的菱形表示法如下:
OT算法在协同编辑中的应用
客户端进行了A操作后,还执行了A2操作,所以第一次OT之后 状态C不是最终状态,而是一种临时状态。B`和A2就要继续OT计算,达到状态D。同时注意这里从等待发送A2 变成了等待放A2`。
服务端则是先收到A操作后 应用A`,而后收到A``。

5 总结

OT算法和一整套完整的设计,确实解决了协同操作的问题,本文通过分析纯文本的协同,讲清楚最核心的关键技术点。对于更复杂的场景则需要设计的原子操作和操作转换算法也会更加的复杂。比如腾讯的在线文档,除了文本之外,还需要同步样式、图片元素等等。留一个问题:既然OT算法可以解决协同操作问题,为什么在使用腾讯在线excel的过程中发现多个人同时操作一个表格单元的时候,会出现相互覆盖的问题?

如果觉得有收获请关注微信公众号 前端良文 分享前端开发中的干货知识点。

OT算法在协同编辑中的应用

点赞
收藏
评论区
推荐文章
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
KubeEdge@MEC:Kubernetes容器生态与5G的结合
摘要:边缘计算技术快速发展,5GMEC边云协同成为最新的发展趋势。前言边缘计算技术快速发展,5GMEC进入商业部署快车道,边云协同成为MEC的普遍诉求,KubeEdge社区洞悉这一趋势,按照CNCF成熟治理模式,成立MECSIG。在MEC场景下,通过对边云协同面临的挑战分析,MECSIG从应用管理、网络、开放生态等几个角
Stella981 Stella981
3年前
SpreadJS 纯前端表格控件应用案例:Teammark知识管理库
由三节课研发的Teammark系统,基于SpreadJS二次开发实现,采用行业优秀的工作方法,以Excel模板作为基本的文档范例,满足了客户在线编辑Excel文档的刚性需求。下面,让我们一起来看看三节课是如何在“Teammark系统”中应用表格技术,实现多人实时协作与“表格文档协同编辑(https://www.oschina.net/action
Stella981 Stella981
3年前
SpreadJS 纯前端表格控件应用案例:SPDQD 质量数据云
由重庆筑智建建筑科技有限公司研发的SPDQD质量数据云,是一套面向广大施工技术人员,针对施工现场质量技术资料在线编制、管理,支持多人实时在线协作的工具。下面,让我们一起来看看重庆筑智建建筑科技有限公司是如何在“SPDQD质量数据云”项目中应用表格技术实现“文档协同编辑”和“数据填报”等功能模块的。项目背景“SPDQD质量数据云”是国
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
User
1基于用户的协同过滤算法:基于用户的协同过滤算法是推荐系统中最古老的的算法,可以说是这个算法的诞生标志了推荐系统的诞生。该算法在1992年被提出,并应用于邮件过滤系统,1994年被GroupLens用于新闻过滤。在一个在线个性化推荐系统中,当一个用户A需要个性化推荐时,可以先找到和他有相似兴趣的其他用户,然后把那些用户喜欢的而用户A没有接触过的物品推
Wesley13 Wesley13
3年前
Java多线程下的协同控制,这些你都知道了吗?
协同控制是并发程序必不可少的重要手段。主要分为两大控制方法,一个是JDK提供的最基础的协同控制方法,一个是java.util.concurrent包下的拓展类控制,接下来我们将会介绍这两种方法有哪些操作可以进行同步控制。一、基础的协同控制线程基础知识因为加锁涉及到多线程,所以有必要先说一下线程的基础知识(定义那
绣鸾 绣鸾
1年前
PhpStorm 2023 for Mac(PHP集成开发IDE)
是一款由JetBrAIns开发的PHP集成开发环境(IDE)。它提供了许多功能来简化PHP应用程序开发,包括代码编辑、调试、代码分析、测试和版本控制等。以下是Phpstorm的一些主要特点:代码编辑器:Phpstorm具有智能代码编辑器,支持语法高亮、代码
云数据库MySQL多人协同开发实践
随着云计算技术的快速发展,云数据库作为云计算的重要组成部分,为企业提供了高效、灵活和可靠的数据存储和管理服务。其中,MySQL作为一款流行的开源关系型数据库,在云数据库领域具有广泛的应用。多人协同开发是软件开发过程中的重要环节,本文将探讨云数据库MySQL多人协同开发的实践。
直播预告 | 大模型时代,“应用变了”:政务办公,如何从大模型中巧借力?
医疗健康,直播娱乐,聊天工具,通勤支付应用融入了我们生活的方方面面。协同办公应用,因具有丰富的文书理解、会议总结、对话摘要等人机交互需求,成为大模型落地产业的最佳应用场景之一而相较普通办公场景政务场景下的协同办公对模型训练、部署、使用提出了更严谨的要求12
促进云边协同发展,我们一直在努力!
7月18日,由中国通信标准化协会主办的第四届“云边协同”大会暨首届分布式算力论坛在北京召开,大会聚焦云边端分布式算力领域技术新突破、应用新场景、发展新价值,搭建政产学研用交流对接平台,深化产业链协同开放合作。