基于OT的多人实时协作系统方案
1. 简介
该文章记录基于文本的多人实时协作系统的可行技术方案,仅包括同步逻辑介绍、具体算法伪码以及同步的流程,不包括工程化代码,该方案基于OT,包含基础的实时同步,并不包括redo/undo、离线同步等feature,下篇博文会介绍基于json数据结构的多人实时协作系统实现方案
2. 同步流程
服务器保存草稿,并维护一个long类型的字段version用于记录此时草稿的版本,version初始值为0,每次有用户提交修改时version会自增
客户端client能够连接服务器获取最新版本的草稿,每当用户修改草稿后client会将数据提交给服务器,服务器处理并成功合并用户的提交后,分发给其他在线client
这里提出同步时会遇到的问题:
- 冲突: 冲突是指多个客户端在同一个版本上对同一个最小编辑单位做了不同的修改
- 数据乱序到达: 因为网络等问题导致多数据乱序到达服务器或者客户端,甚至出现未到达等情况
后续在协作流程中会解决该问题
3. 定义
对系统中主要概念进行定义
3.1 文档[Document]
- 文档可以是一个字符数组或者是一个字符串
- 文档也可以表示为一个操作集[Changesets]的数组
3.2 操作集[Changesets]
- 操作集代表对文档的一次操作
- 可以在文档上对操作集进行一次Apply操作,用于将某个操作集合并到文档中
3.3 操作集数据结构
- 操作集表示为
(l->l')[c1, c2, c3, ...]
- 其中
- l 表示修改前文档的长度
- l’ 表示修改后文档的长度
- [c1, c2, c3, …] 表示操作后的字符数组
- [c1, c2, c3, …]数组中的任意元素ci,ci不是数字就是字符
- 当ci为数字时,表示该位置的字符串未改变,依旧是原始文档中的字符
- 当ci为字符时,表示该位置插入了一个新的字符ci
3.4 操作集的限制
- 操作集必须是统一规范并且可以比较的(equals),我们使用相同的操作集代表相同的操作,因此若记录两个不同的操作,则必须得到不同的操作集
- 操作集的表示要紧凑,若内存中有多种方式可以表示操作时,应使用字节占用最小的方式去表示
3.5 符号表示
- 使用代数中的乘法表示apply操作,即将操作集应用到另一个文档上
- e.g.
A = (0->5)["hello"] B = (5->11)[0-4,"world"]
- 可以将 “hello world” 计作 A * B 或者 AB
- e.g.
3.6 操作集的组合[Composition of Changesets]
-
假设存在操作集A、B
A = (n1 -> n2)[...]