当前位置:首页 > 科技  > 软件

可视化+多人协同技术原理和案例分享

来源: 责编: 时间:2024-04-25 17:43:43 95观看
导读前言hi,大家好,我是徐小夕,之前和大家分享了很多可视化低代码的技术实践,最近也做了一款非常有意思的文档搭建引擎——Nocode/Doc:接下来和大家分享另一个比较有意思的话题——多人协同技术。文章大纲多人协同技术方案探讨

WVA28资讯网——每日最新资讯28at.com

前言

hi,大家好,我是徐小夕,之前和大家分享了很多可视化低代码的技术实践,最近也做了一款非常有意思的文档搭建引擎——Nocode/Doc:WVA28资讯网——每日最新资讯28at.com

WVA28资讯网——每日最新资讯28at.com

接下来和大家分享另一个比较有意思的话题——多人协同技术。WVA28资讯网——每日最新资讯28at.com

文章大纲

  • 多人协同技术方案探讨
  • OT和CRDT算法
  • 插曲(互斥锁(Mutex)原理和代码实现)
  • yjs协同框架使用
  • yjs多人协同案例

多人协同技术方案探讨

多人协同技术方案常见的应用场景主要有:WVA28资讯网——每日最新资讯28at.com

  • 原型工具(axure,某刀,mastergo等)
  • 文档办公类 (飞书文档,钉钉文档,石墨文档等)
  • 设计工具(即时设计,figma等)

主要目的是实现多个人同时编辑一份共享资源, 来提高工作效率。WVA28资讯网——每日最新资讯28at.com

WVA28资讯网——每日最新资讯28at.com

抛开已有技术本身,我们拿最简单的富文本编辑器为例子, 如果我们想让它实现多人同时编辑,有哪些可以想到的方案呢?WVA28资讯网——每日最新资讯28at.com

  • 覆盖模式

即每个人保存时都强制以自己的版本为主,即保存最后一次修改,这样会导致的问题是无法实现真正意义上的共享协作。WVA28资讯网——每日最新资讯28at.com

  • 锁模式

也就是对文件”上锁“。当某个用户正在编辑文档时,对此文档进行加锁处理,避免多人同时编辑,从而避免文档的内容冲突。 缺点就是用户体验不友好,并且需要等待时间。WVA28资讯网——每日最新资讯28at.com

  • diff 模式

我们可以采用类似 git 的版本管理模式,多人编辑时利用 webrtc / socket 与服务端通信,保存时通过服务端进行差异对比、合并,自动进行冲突处理,再通过服务推送如SSE(服务端实时主动向浏览器推送消息的技术)的方式推送给其他人。WVA28资讯网——每日最新资讯28at.com

弊端是会出现类似 git 修改同一行,纯靠服务端无法处理,需要手动处理冲突。WVA28资讯网——每日最新资讯28at.com

这里给大家推荐一个有意思的库 NodeGit。WVA28资讯网——每日最新资讯28at.com

github地址: https://github.com/nodegit/nodegitWVA28资讯网——每日最新资讯28at.com

以下是 NodeGit 的一些主要特点:WVA28资讯网——每日最新资讯28at.com

  • 全功能:几乎支持 Git 的所有命令,如克隆、提交、拉取、合并等。
  • 高性能:直接调用 C 库,提供接近原生速度的性能。
  • 易于集成:作为一个 Node.js 模块,可轻松融入任何 Node.js 项目,无需额外的构建步骤或依赖。
  • 跨平台:支持 Windows、macOS 和 Linux,让开发者可以在各种操作系统上工作。
  • 文档齐全:提供详细的 API 文档和示例代码,便于理解和使用。
  • 社区活跃:开源社区活跃,问题和 PR 能得到及时响应,不断更新改进。

NodeGit 可以用于多个领域,例如自动化部署、协作工具、代码分析、教育工具和 CI/CD 系统等。通过使用 NodeGit,我们能以编程方式访问和操作 Git 存储库,实现更灵活和自动化的版本控制流程。WVA28资讯网——每日最新资讯28at.com

当然以上这几种方式很难应对复杂场景的多人协作。WVA28资讯网——每日最新资讯28at.com

OT和CRDT算法

OT 算法是一种用于实时协同编辑的算法,它通过操作 & 转换来实现数据的一致性。在 OT 算法中,每个用户对数据的操作(如修改、删除等)都被记录下来,并在其他用户的客户端进行相应的转换,从而实现多个用户对同一份数据的协同编辑。WVA28资讯网——每日最新资讯28at.com

OT 算法的优点在于它可以实时地反映用户的操作,并且可以很好地处理并发冲突。但是 OT 算法需要在中心化的服务器上进行协同调度,因此对于大规模的分布式系统来说不太适用。WVA28资讯网——每日最新资讯28at.com

操作 Operational

基于 OT 的协同编辑核心是:将文档的每一次修改看作是一个操作,即操作原子化处理,如在第 N 个位置插入一个字符时,客户端会将操作发送到服务端去处理。WVA28资讯网——每日最新资讯28at.com

以quill富文本编辑器举例, 它通过 retain、insert、delete 三个操作完成整篇文档的描述与操作,如下:WVA28资讯网——每日最新资讯28at.com

[    // Unbold and italicize "Gandalf"    { retain: 7, attributes: { bold: null, italic: true } },    // Keep " the " as is    { retain: 5 },    // Insert "White" formatted with color #fff    { insert: 'White', attributes: { color: '#fff' } },    // Delete "Grey"    { delete: 4 }  ]

相关地址:https://quilljs.com/docs/deltaWVA28资讯网——每日最新资讯28at.com

Transformation 转换

WVA28资讯网——每日最新资讯28at.com

用户将原子化的操作发送到服务端时(必须有中央服务器进行调度), 服务端对多个客户端的操作进行转换,对客户端操作中的并发冲突进行修正,确保当前操作同步到其他设备时得到一致的结果,因为对冲突的处理都是在服务端完成,所以客户端得到的结果一定是一致的,也就是说 OT 算法的结果保证强一致性。WVA28资讯网——每日最新资讯28at.com

转换完成后,通过网络发送到对应用户,用户合并操作,从而得到一致结果。WVA28资讯网——每日最新资讯28at.com

这意味着 OT 算法对网络要求更高,如果某个用户出现网络异常,导致一些操作缺失或延迟,那么服务端的转换就会出现问题。WVA28资讯网——每日最新资讯28at.com

OT算法可视化模型:https://operational-transformation.github.io/index.htmlWVA28资讯网——每日最新资讯28at.com

CRDT

CRDT 算法全称 Conflict-free Replicated Data Type,即无冲突复制数据类型,是一种基于数据结构的无冲突复制数据类型算法,它通过数据结构的合并来实现数据的一致性。WVA28资讯网——每日最新资讯28at.com

在 CRDT 算法中,每个用户对数据的修改都会被记录下来,并在其他用户的客户端进行合并,以实现数据的一致性。CRDT 算法的优点在于它可以适用于大规模的分布式系统,并且不需要中心化的服务器进行协同调度。WVA28资讯网——每日最新资讯28at.com

但是,CRDT 算法在处理复杂操作时可能会存在合并冲突的问题,需要设计复杂的合并函数来解决。WVA28资讯网——每日最新资讯28at.com

Yjs 是专门为在 web 上构建协同应用程序而设计的CRDT。WVA28资讯网——每日最新资讯28at.com

CRDT 包含以下两种:WVA28资讯网——每日最新资讯28at.com

  • CmRDT:基于操作的 CRDT,OP-based-CRDT
  • CvRDT:基于状态的 CRDT,State-based CRDT

基于状态的 CRDT 更容易设计和实现,每个 CRDT 的整个状态最终都必须传输给其他每个副本,每个副本之间通过同步全量状态达到最终一致状态,这可能开销很大;WVA28资讯网——每日最新资讯28at.com

而基于操作的 CRDT 只传输更新操作,各副本之间通过同步操作来达到最终一致状态,通常很小。WVA28资讯网——每日最新资讯28at.com

穿插一个小概念:WVA28资讯网——每日最新资讯28at.com

向量时钟(Vector Clock),它是一种在分布式系统中用于记录事件顺序的时间戳机制。它的主要目的是在分布式环境中实现事件的并发控制和一致性。WVA28资讯网——每日最新资讯28at.com

向量时钟的基本思想是为系统中的每个节点维护一个向量,其中每个分量对应一个节点,用于记录该节点的事件发生次数。当一个节点发生事件时,它会增加自己分量的值。向量时钟的关键是在不同节点之间传递这些向量,并在合并时确保一致性。WVA28资讯网——每日最新资讯28at.com

目前协同算法底层都会采用向量时钟的模式来设计操作算法。WVA28资讯网——每日最新资讯28at.com

插曲(互斥锁(Mutex)原理和代码实现)

先上代码:WVA28资讯网——每日最新资讯28at.com

const createMutex = () => {    let token = true    return (f, g) => {        if (token) {            token = false            try {                f()            } finally {                token = true            }        } else if (g !== undefined) {            g()        }    }}

它用于创建一个互斥锁(Mutex)。互斥锁是一种用于控制资源访问的机制,确保在任何给定的时间只有一个线程(在这里可以理解为一个函数调用)可以访问被保护的资源或代码块。WVA28资讯网——每日最新资讯28at.com

下面是对代码中每个部分的解释:WVA28资讯网——每日最新资讯28at.com

  • let token = true:创建一个名为token的变量,并将其初始化为true。token用于表示互斥锁的状态。
  • return (f, g) => { ... }:返回一个箭头函数,该函数接受两个参数f和g。
  • if (token) { ... }:如果token为true,表示互斥锁可用。
  • token = false:将token设置为false,表示当前函数获取了互斥锁。
  • try { f() } finally { token = true }:在try块中执行传入的函数f。如果在执行f的过程中发生异常,会跳转到finally块中。在finally块中,将token重新设置为true,表示释放互斥锁。
  • else if (g !== undefined) { g() }:如果token为false,表示互斥锁已被其他函数获取。如果同时还传递了第二个参数g,则执行g函数。

通过这种方式,createMutex 函数创建了一个简单的互斥锁机制。只有在互斥锁可用时,才能执行f函数。如果互斥锁已被其他函数获取,将跳过f函数的执行,并在可能的情况下执行g函数。WVA28资讯网——每日最新资讯28at.com

这种互斥锁的实现通常用于在多线程或异步环境中确保对共享资源的安全访问。WVA28资讯网——每日最新资讯28at.com

yjs协同框架使用

Yjs 本身是一个数据结构,原理是:当多人协作时,对于文档内容修改,通过中间层将文档数据转换成 CRDT 数据;通过 CRDT 进行数据数据更新这种增量的同步,通过中间层将 CRDT 的数据转换成文档数据,另一个协作方就能看到对方内容的更新。WVA28资讯网——每日最新资讯28at.com

中间内容的更新是基于 Yjs 数据结构进行的,冲突处理等核心都是 Yjs 承担的,通信基于 websocket 或 webrtc,所以我们只需要简单的使用就可以实现多人协同的应用。WVA28资讯网——每日最新资讯28at.com

下面是我总结的一个结构:WVA28资讯网——每日最新资讯28at.com

WVA28资讯网——每日最新资讯28at.com

Yjs 基于数据结构层面处理冲突,比 OT 更加稳健,对复杂网络的适应性更强。网络延时或离线编辑对数据结构来说,处理没有任何差异。WVA28资讯网——每日最新资讯28at.com

我总结了一下它的几个核心特点:WVA28资讯网——每日最新资讯28at.com

  • 协同列表及光标位置

Yjs 提供的 Awareness(意识)模块,名如其意,让协作者能够意识到其他人的位置在哪,有效避免冲突可能性。WVA28资讯网——每日最新资讯28at.com

  • 离线编辑

基于 CRDT 的内容合并,天然支持离线编辑,浏览器端做本地化存储。WVA28资讯网——每日最新资讯28at.com

  • 版本历史支持

Yjs 自身提供了快照机制,保存历史版本不用保存全量数据,只是基于 Yjs 打一个快照,后续基于快照恢复历史版本。WVA28资讯网——每日最新资讯28at.com

  • 系统编辑人数上限

上限人数很高,可支持很多人同时编辑。WVA28资讯网——每日最新资讯28at.com

目前主流的 figma 也是采用的 CRDT 开发协同编辑功能。WVA28资讯网——每日最新资讯28at.com

yjs使用

WVA28资讯网——每日最新资讯28at.com

以上我根据自己的理解整理了一下yjs的核心模块。接下来我以数组结构为例子给大家介绍一下它的用法:WVA28资讯网——每日最新资讯28at.com

import * as Y from 'yjs'const ydoc = new Y.Doc()// 1: 定义一个类型为数组的共享数据结构const yarray = ydoc.getArray('my doc') // 2. 向数组中插入数据,在第一个位置插入3条数据yarray.insert(0, [1, 2, 3]) // 3. 在第二个位置删除一条数据yarray.delete(1, 1)// 4. 获取可用的结果yarray.toArray() // => [1, 3]// 5. 监听数据变化,执行操作yarray.observeDeep((event) => {  console.log(event)})// 将连续的操作合并到transact 中ydoc.transact(() => {  yarray.insert(1, ['a', 'b'])  yarray.delete(2, 2) // deletes 'b' and 2}) // => [{ retain: 1 }, { insert: ['a'] }, { delete: 1 }]

transact方法用于执行事务操作。事务是共享文档上的一系列更改,这些更改会在一个事务中进行处理,以保证数据的一致性和正确性。每个事务都会触发Observer调用和update事件,我们可以在这些事件中进行相应的处理。WVA28资讯网——每日最新资讯28at.com

通过将更改捆绑到单个事务中,可以减少事件调用的次数,并确保数据的一致性。在事务中,我们可以进行多种操作,如插入、删除、修改等。WVA28资讯网——每日最新资讯28at.com

yjs多人协同案例

WVA28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-85549-0.html可视化+多人协同技术原理和案例分享

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 玉伯、狼叔来了...这场大前端大会绝对不容错过

下一篇: 新机新选择!轻薄 5G 拍照手机新品 Hi nova 12 SE 强势登场

标签:
  • 热门焦点
Top