二手书交易网站开发背景分析,wordpress 链接打不开,网站节点加速,欧米茄官网网站前言 hi#xff0c;大家好#xff0c;我是徐小夕#xff0c;之前和大家分享了很多可视化低代码的技术实践#xff0c;最近也做了一款非常有意思的文档搭建引擎——Nocode/Doc#xff1a; 也做了一些分享#xff1a; Nocode/Doc#xff0c;可视化 零代码打造下一代文件编… 前言 hi大家好我是徐小夕之前和大家分享了很多可视化低代码的技术实践最近也做了一款非常有意思的文档搭建引擎——Nocode/Doc 也做了一些分享 Nocode/Doc可视化 零代码打造下一代文件编辑器爆肝1000小时, Dooring零代码搭建平台3.5正式上线 接下来和大家分享另一个比较有意思的话题——多人协同技术。 文章大纲 多人协同技术方案探讨OT和CRDT算法插曲互斥锁Mutex原理和代码实现yjs协同框架使用yjs多人协同案例 多人协同技术方案探讨 多人协同技术方案常见的应用场景主要有 原型工具axure某刀mastergo等文档办公类 飞书文档钉钉文档石墨文档等设计工具即时设计figma等 主要目的是实现多个人同时编辑一份共享资源, 来提高工作效率。 抛开已有技术本身我们拿最简单的富文本编辑器为例子 如果我们想让它实现多人同时编辑有哪些可以想到的方案呢 覆盖模式 即每个人保存时都强制以自己的版本为主即保存最后一次修改这样会导致的问题是无法实现真正意义上的共享协作。 锁模式 也就是对文件”上锁“。当某个用户正在编辑文档时对此文档进行加锁处理避免多人同时编辑从而避免文档的内容冲突。 缺点就是用户体验不友好并且需要等待时间。 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富文本编辑器举例 它通过 retain、insert、delete 三个操作完成整篇文档的描述与操作如下: [// 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 转换 用户将原子化的操作发送到服务端时必须有中央服务器进行调度 服务端对多个客户端的操作进行转换对客户端操作中的并发冲突进行修正确保当前操作同步到其他设备时得到一致的结果因为对冲突的处理都是在服务端完成所以客户端得到的结果一定是一致的也就是说 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基于操作的 CRDTOP-based-CRDTCvRDT基于状态的 CRDTState-based CRDT 基于状态的 CRDT 更容易设计和实现每个 CRDT 的整个状态最终都必须传输给其他每个副本每个副本之间通过同步全量状态达到最终一致状态这可能开销很大 而基于操作的 CRDT 只传输更新操作各副本之间通过同步操作来达到最终一致状态通常很小。 穿插一个小概念 向量时钟Vector Clock它是一种在分布式系统中用于记录事件顺序的时间戳机制。它的主要目的是在分布式环境中实现事件的并发控制和一致性。 向量时钟的基本思想是为系统中的每个节点维护一个向量其中每个分量对应一个节点用于记录该节点的事件发生次数。当一个节点发生事件时它会增加自己分量的值。向量时钟的关键是在不同节点之间传递这些向量并在合并时确保一致性。 目前协同算法底层都会采用向量时钟的模式来设计操作算法。 插曲互斥锁Mutex原理和代码实现 先上代码 const createMutex () {let token truereturn (f, g) {if (token) {token falsetry {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 承担的通信基于 websocket 或 webrtc所以我们只需要简单的使用就可以实现多人协同的应用。 下面是我总结的一个结构 Yjs 基于数据结构层面处理冲突比 OT 更加稳健对复杂网络的适应性更强。网络延时或离线编辑对数据结构来说处理没有任何差异。 我总结了一下它的几个核心特点 协同列表及光标位置 Yjs 提供的 Awareness意识模块名如其意让协作者能够意识到其他人的位置在哪有效避免冲突可能性。 离线编辑 基于 CRDT 的内容合并天然支持离线编辑浏览器端做本地化存储。 版本历史支持 Yjs 自身提供了快照机制保存历史版本不用保存全量数据只是基于 Yjs 打一个快照后续基于快照恢复历史版本。 系统编辑人数上限 上限人数很高可支持很多人同时编辑。 目前主流的 figma 也是采用的 CRDT 开发协同编辑功能。 yjs使用 以上我根据自己的理解整理了一下yjs的核心模块。接下来我以数组结构为例子给大家介绍一下它的用法 import * as Y from yjsconst 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多人协同案例 最后 好啦。这就是本周的更新预计4月29号会做一波更大规模的更新和功能上线欢迎随时和我留言反馈建议技术交流~ 大家也可以关注我的视频号后续会做更多的零代码技术产品分享~ 往期精彩 Nocode/Doc可视化 零代码打造下一代文件编辑器爆肝1000小时, Dooring零代码搭建平台3.5正式上线可视化表单试卷搭建平台技术详解