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

前言

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

d95c0cd804877e2804b6a0f863cad2f1.png

也做了一些分享:

  • Nocode/Doc,可视化+ 零代码打造下一代文件编辑器

  • 爆肝1000小时, Dooring零代码搭建平台3.5正式上线

接下来和大家分享另一个比较有意思的话题——多人协同技术

文章大纲

  • 多人协同技术方案探讨

  • OT和CRDT算法

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

  • yjs协同框架使用

  • yjs多人协同案例

多人协同技术方案探讨

多人协同技术方案常见的应用场景主要有:

  • 原型工具(axure,某刀,mastergo等)

  • 文档办公类 (飞书文档,钉钉文档,石墨文档等)

  • 设计工具(即时设计,figma等)

主要目的是实现多个人同时编辑一份共享资源, 来提高工作效率。

50b79a410428b7d9258fe8291d86c562.png

抛开已有技术本身,我们拿最简单的富文本编辑器为例子, 如果我们想让它实现多人同时编辑,有哪些可以想到的方案呢?

  • 覆盖模式

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

  • 锁模式

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

  • diff 模式

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

弊端是会出现类似 git 修改同一行,纯靠服务端无法处理,需要手动处理冲突。

这里给大家推荐一个有意思的库 NodeGit

github地址: https://github.com/nodegit/nodegit

以下是 NodeGit 的一些主要特点:

  • 全功能:几乎支持 Git 的所有命令,如克隆、提交、拉取、合并等。

  • 高性能:直接调用 C 库,提供接近原生速度的性能。

  • 易于集成:作为一个 Node.js 模块,可轻松融入任何 Node.js 项目,无需额外的构建步骤或依赖。

  • 跨平台:支持 Windows、macOS 和 Linux,让开发者可以在各种操作系统上工作。

  • 文档齐全:提供详细的 API 文档和示例代码,便于理解和使用。

  • 社区活跃:开源社区活跃,问题和 PR 能得到及时响应,不断更新改进。

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

当然以上这几种方式很难应对复杂场景的多人协作。

OT和CRDT算法

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

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

操作 Operational

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

quill富文本编辑器举例, 它通过 retaininsertdelete 三个操作完成整篇文档的描述与操作,如下:

[
    // 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/delta

Transformation 转换
d150a5d22bfd826dd33506b3f70bde8e.png

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

转换完成后,通过网络发送到对应用户,用户合并操作,从而得到一致结果。

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

OT算法可视化模型:https://operational-transformation.github.io/index.html

CRDT

CRDT 算法全称 Conflict-free Replicated Data Type,即无冲突复制数据类型,是一种基于数据结构的无冲突复制数据类型算法,它通过数据结构的合并来实现数据的一致性

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

但是,CRDT 算法在处理复杂操作时可能会存在合并冲突的问题,需要设计复杂的合并函数来解决。

Yjs 是专门为在 web 上构建协同应用程序而设计的CRDT.

CRDT 包含以下两种:

  • CmRDT:基于操作的 CRDT,OP-based-CRDT

  • CvRDT:基于状态的 CRDT,State-based CRDT

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

而基于操作的 CRDT 只传输更新操作,各副本之间通过同步操作来达到最终一致状态,通常很小。

穿插一个小概念:

向量时钟(Vector Clock),它是一种在分布式系统中用于记录事件顺序的时间戳机制。它的主要目的是在分布式环境中实现事件的并发控制和一致性。

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

目前协同算法底层都会采用向量时钟的模式来设计操作算法。

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

先上代码:

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

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

下面是对代码中每个部分的解释:

  • 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函数。

这种互斥锁的实现通常用于在多线程或异步环境中确保对共享资源的安全访问

yjs协同框架使用

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

中间内容的更新是基于 Yjs 数据结构进行的,冲突处理等核心都是 Yjs 承担的,通信基于 websocketwebrtc,所以我们只需要简单的使用就可以实现多人协同的应用。

下面是我总结的一个结构:

13f77f4337e38ccf95806a20723273e5.png

Yjs 基于数据结构层面处理冲突,比 OT 更加稳健,对复杂网络的适应性更强。网络延时或离线编辑对数据结构来说,处理没有任何差异。

我总结了一下它的几个核心特点:

  • 协同列表及光标位置

Yjs 提供的 Awareness(意识)模块,名如其意,让协作者能够意识到其他人的位置在哪,有效避免冲突可能性。

  • 离线编辑

基于 CRDT 的内容合并,天然支持离线编辑,浏览器端做本地化存储。

  • 版本历史支持

Yjs 自身提供了快照机制,保存历史版本不用保存全量数据,只是基于 Yjs 打一个快照,后续基于快照恢复历史版本。

  • 系统编辑人数上限

上限人数很高,可支持很多人同时编辑。

目前主流的 figma 也是采用的 CRDT 开发协同编辑功能。

yjs使用
dc9f4086640f4f6693619b64aa2524f5.png

以上我根据自己的理解整理了一下yjs的核心模块。接下来我以数组结构为例子给大家介绍一下它的用法:

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事件,我们可以在这些事件中进行相应的处理。

通过将更改捆绑到单个事务中,可以减少事件调用的次数,并确保数据的一致性。在事务中,我们可以进行多种操作,如插入、删除、修改等。

yjs多人协同案例

feef638f871da3315ee58fb521c2ad59.png

最后

好啦。这就是本周的更新,预计4月29号会做一波更大规模的更新和功能上线,欢迎随时和我留言反馈,建议,技术交流~

大家也可以关注我的视频号,后续会做更多的零代码技术产品分享~

往期精彩:
  • Nocode/Doc,可视化+ 零代码打造下一代文件编辑器

  • 爆肝1000小时, Dooring零代码搭建平台3.5正式上线

  • 可视化表单&试卷搭建平台技术详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/575580.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity读书系列《Unity3D游戏开发》——脚本(一)

文章目录 前言一、脚本模版及其拓展1、脚本模版2、拓展脚本模版 二、脚本的生命周期三、脚本的执行顺序四、脚本序列化1、序列化数据2、serializedObject3、监听部分元素修改事件 五、定时器与间隔定时器六、工作线程(多线程)总结 前言 脚本在Unity的重…

Rust HTTP 客户端:易于使用、功能强大 | 开源日报 No.228

seanmonstar/reqwest Stars: 8.9k License: Apache-2.0 reqwest 是一个易于使用且功能强大的 Rust HTTP 客户端。 异步和阻塞客户端支持普通数据、JSON、urlencoded 和 multipart 数据格式可定制的重定向策略支持 HTTP 代理和系统原生 TLS 或 rustls 的 HTTPSCookie 存储功能…

RoadBEV:鸟瞰图中的道路表面重建

1. 代码地址 GitHub - ztsrxh/RoadBEV: Codes for RoadBEV: road surface reconstruction in Birds Eye View 2. 摘要 本文介绍了RoadBEV:鸟瞰图中的道路表面重建。道路表面条件(特别是几何形状)极大地影响了自动驾驶汽车的驾驶性能。基于…

就业班 第三阶段(nginx) 2401--4.22 day1 nginx1 http+nginx初识+配置+虚拟主机

一、HTTP 介绍 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。 HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件…

ubuntu安装Qv2ray2.7.0及配置

需要下载两个文件,一个是zip文件,一个是AppImage执行程序。 执行AppImage需要先下载fuse sudo apt install libfuse2然后为AppImage赋予执行权限 sudo chmod x ./Qv2ray-v2.7.0-linux-x64.AppImage执行,执行前可以解压zip文件 ./Qv2ray-refs.tags.v1…

操作系统(Operating System)知识点复习——第十一章 I/O管理与磁盘调度

目录 0.前言 1.I/O设备 2.I/O功能的组织 3.Operating System Design Issues 4.I/O缓冲 4.1 单缓冲Single Buffer 4.2 双缓冲Double Buffer 4.3 循环缓冲 5.磁盘调度Disk Scheduling 5.1 磁盘性能参数 5.2 磁盘调度策略 ①First-in,first-out(FIFO) ②Pr…

鸿蒙ArkUI实战开发-如何通过上下滑动实现亮度和音量调节

场景说明 在音视频应用中通常可以通过上下滑动来调节屏幕亮度和音量大小,本例即为大家介绍如何实现上述UI效果。 说明: 由于当前亮度和音量调节功能仅对系统应用开发,所以本例仅讲解UI效果的实现。 效果呈现 本例效果如下: 当在…

决策树分析及其在项目管理中的应用

决策树分析是一种分类学习方法,其主要用于解决分类和回归问题。在决策树中,每个内部节点表示一个属性上的测试,每个分支代表一个属性输出,而每个叶节点则代表类或类分布。通过从根节点到内部节点的路径,可以构建一系列…

Haystack

文章目录 关于 Haystack提供 NLP项目所有阶段的功能 Building blocks组件 Components管道 Pipelines代理 Agents 基本使用 - RAG 关于 Haystack 官网:https://haystack.deepset.ai官方文档:https://docs.haystack.deepset.ai/docs/intro教程&#xff1a…

IP地址定位是怎么实现的?

IP地址定位技术的实现是一个涉及多方面技术和方法的复杂过程。IP地址作为互联网通信中的关键元素,每个设备在网络中都被分配一个唯一的IP地址,用于标识和定位网络上的设备。通过一系列技术手段,我们可以对这些IP地址进行分析,进而…

MATLAB 向量

MATLAB 向量 向量是一维数字数组。MATLAB允许创建两种类型的向量 行向量 列向量 行向量 行向量通过将元素集括在方括号中并使用空格或逗号定界元素来创建。 示例 r [7 8 9 10 11] MATLAB将执行上述语句并返回以下结果- r 7 8 9 10 11 列向量 列向量 通过将元素集括在方…

大型网站系统架构演化实例_6.使用分布式文件系统和分布式数据库系统

1.使用分布式文件系统和分布式数据库系统 任何强大的单一服务器都满足不了大型网站持续增长的业务需求。数据库经过读写分离后,从一台服务器拆分成两台服务器,但是随着网站业务的发展依然不能满足需求,这时需要使用分布式数据库。文件系统也一…

【高校科研前沿】东北地理所在遥感领域顶刊RSE发布中国主要红树植物群落遥感分类成果

目录 01 文章简介 02 研究内容 03 文章引用 01 文章简介 论文名称:Mangrove species mapping in coastal China using synthesized Sentinel-2 high-separability images(基于Sentinel-2高分离度图像的中国沿海红树群落制图) 第一作者及…

python爬虫学习------scrapy第二部分(第三十天)

🎈🎈作者主页: 喔的嘛呀🎈🎈 🎈🎈所属专栏:python爬虫学习🎈🎈 ✨✨谢谢大家捧场,祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天…

(51单片机)第十三章-STC系列51单片机功能介绍

13.1 单片机空闲与掉电模式的应用 1. 空闲模式 当单片机进入空闲模式时,除CPU处于休眠状态外,其余硬件全部处于活动状态,芯片中程序未涉及的数据存储器和特殊功能寄存器中的数据在空闲模式期间都将保持原值。假若定时器正在运行,…

第一篇:Python简介:开启你的编程之旅

Python简介:开启你的编程之旅 在这个系列文章中,我将带领大家深入了解Python——一个极具魅力的编程语言。如果你对编程感兴趣,想要掌握一门既实用又强大的语言,那么Python无疑是一个绝佳的选择。本篇文章是这个系列的序章&#…

大数据基础

基本简介 大数据特点 数据量大 种类多样 结构化:多指关系型数据库中,信用卡号码、日期、财务金额、电话号码、地址 半结构化:xml/json 非结构化:全文文本、图象、声音、影视、超媒体等信息。 应用价值高 大数据的作用 追溯…

protobuf协议逆向解析

protobuf协议逆向解析 地址: aHR0cHM6Ly93d3cudGlrdG9rLmNvbS9tZXNzYWdlcz9sYW5nPWVu找到接口/v2/message/get_by_user_init 如图所示, 参数和响应并不是可直接使用的, 虽然部分内容可读。 跟栈到这里, 找到封包前的数据 打上断点, 查看变量t就是请…

数字安全实操AG网址漏洞扫描原理与技术手段分析

在数字化世界的大舞台上,网络安全如同守护者一般,默默保卫着我们的虚拟疆界。当我们在享受互联网带来的便利时,一场无形的战争正在上演。黑客们利用各种手段试图攻破网站的安全防线,而防守方则依靠先进的技术和策略来抵御入侵。其…

武汉星起航:创新孵化模式,一站式服务助力卖家全球化拓展

在全球化浪潮席卷而来的今天,跨境电商行业已成为推动国际贸易的重要力量。武汉星起航电子商务有限公司,作为这一领域的佼佼者,以其前瞻性的战略眼光和创新的经营模式,积极践行“走出去”战略,凭借自营店铺运营经验和跨…
最新文章