国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

代碼里的“和平協(xié)議”:用MoonBit實(shí)現(xiàn)無(wú)沖突的多人編輯

0
分享至


作者:東燈原標(biāo)題:用 MoonBit 實(shí)現(xiàn) CRDTs 算法并構(gòu)建實(shí)時(shí)協(xié)作應(yīng)用
一.引言

當(dāng)你在 Google Docs 中與同事同時(shí)編輯一份文檔,或者在 Figma 中與設(shè)計(jì)師協(xié)作調(diào)整界面時(shí),你有沒(méi)有想過(guò):為什么兩個(gè)人同時(shí)在同一位置輸入文字,最終結(jié)果卻不會(huì)互相覆蓋或產(chǎn)生亂碼?

這背后隱藏著分布式系統(tǒng)中最具挑戰(zhàn)性的問(wèn)題之一:并發(fā)沖突( Concurrent Conflict)。當(dāng)多個(gè)用戶同時(shí)編輯同一份數(shù)據(jù),且這些編輯需要在不同設(shè)備之間同步時(shí),如何保證所有人最終看到相同的結(jié)果?

本文將帶你深入理解實(shí)時(shí)協(xié)作的核心算法演進(jìn)——從經(jīng)典的操作轉(zhuǎn)換(OT)到經(jīng)典的 CRDTs 算法 RGA,再到現(xiàn)代的 EG-Walker。我們不僅會(huì)解釋這些算法的原理,還會(huì)用 MoonBit 實(shí)現(xiàn)算法的核心邏輯,并最終展示如何用它構(gòu)建一個(gè)簡(jiǎn)單的、斷網(wǎng)重連可合并的協(xié)作編輯器。

二.實(shí)時(shí)協(xié)作的核心挑戰(zhàn)

假設(shè)我們要構(gòu)建一個(gè)多人協(xié)作的文本編輯器。每個(gè)用戶在自己的設(shè)備上都有一份文檔副本,當(dāng)用戶進(jìn)行編輯時(shí),操作會(huì)通過(guò)網(wǎng)絡(luò)同步給其他用戶。為了保證流暢的編輯體驗(yàn),用戶的輸入應(yīng)該立即生效,而不是等待服務(wù)器確認(rèn)。

問(wèn)題來(lái)了:當(dāng)兩個(gè)用戶同時(shí)編輯時(shí),會(huì)發(fā)生什么?讓我們考慮這個(gè)場(chǎng)景:


這就是并發(fā)沖突的本質(zhì):相同的操作序列,以不同順序應(yīng)用,可能產(chǎn)生不同的結(jié)果 。

我們需要的是一種機(jī)制,無(wú)論操作以什么順序到達(dá),最終所有人看到的結(jié)果都相同,而且尊重所有編輯參與者的貢獻(xiàn)。這個(gè)性質(zhì)叫做 最終一致性 (Eventual Consistency) 。

三.操作轉(zhuǎn)換( OT )
1、原理與簡(jiǎn)單實(shí)現(xiàn)

操作轉(zhuǎn)換(Operational Transformation,OT)是最早用于解決實(shí)時(shí)協(xié)作沖突的算法,誕生于 1989 年。Google Docs、Etherpad 等早期協(xié)作工具都采用了這種方案。OT 的基本思路是:既然操作之間會(huì)互相影響,那就在應(yīng)用操作之前,根據(jù)已發(fā)生的操作對(duì)其進(jìn)行“轉(zhuǎn)換”,使其適應(yīng)當(dāng)前狀態(tài)。


看看 OT 是如何解決沖突的:

  • 初始文檔是 AB 。Alice 在位置 1 插入 X ,本地變成 AXB ;Bob 在位置 1 插入 Y ,本地變成 AYB 。現(xiàn)在雙方需要同步對(duì)方的操作。

  • 當(dāng) Alice 收到 Bob 的操作 insert(1, 'Y') 時(shí),她不能直接執(zhí)行——因?yàn)樗呀?jīng)在位置 1 插入了 X ,后面的字符都向右移了一位。OT 發(fā)現(xiàn) Bob 的插入位置(1)不在 Alice 插入位置之前,于是把位置 +1,變成 insert(2, 'Y') 。Alice 執(zhí)行后得到 AXYB 。

  • 同樣,Bob 收到 Alice 的 insert(1, 'X') 。但 Alice 的插入位置(1)不比 Bob 的(1)大,所以不調(diào)整。Bob 直接執(zhí)行,在位置 1 插入 X ,也得到 AXYB 。

不妨簡(jiǎn)單用 MoonBit 實(shí)現(xiàn)一下:

enum Op {
Insert(Int, Char) // Insert(位置, 字符)
Delete(Int) // Delete(位置)
}


/// 轉(zhuǎn)換函數(shù):將 op1 轉(zhuǎn)換為在 op2 已經(jīng)執(zhí)行后的等效操作
fn transform(op1 : Op, op2 : Op) -> Op {
match (op1, op2) {
(Insert(pos1, ch), Insert(pos2, _)) =>
Insert(if pos1 <= pos2 { pos1 } else { pos1 + 1 }, ch)
(Insert(pos1, ch), Delete(pos2)) =>
Insert(if pos1 <= pos2 { pos1 } else { pos1 - 1 }, ch)
// ... 其他 case 類似
}
}

2、OT 存在的問(wèn)題

OT 在工業(yè)界有廣泛應(yīng)用(Google Docs 就基于 OT),但它有一些根本性的問(wèn)題:

1、需要中央服務(wù)器 :OT 需要一個(gè)權(quán)威的服務(wù)器來(lái)確定操作的全局順序。沒(méi)有服務(wù)器,就無(wú)法確定誰(shuí)的操作“先”發(fā)生。

2、轉(zhuǎn)換規(guī)則復(fù)雜度爆炸 :如果有 N 種操作類型,就需要定義 N2 個(gè)轉(zhuǎn)換規(guī)則。當(dāng)操作類型增多(如富文本的加粗、斜體、鏈接等),復(fù)雜度急劇上升。

3、長(zhǎng)分支合并極慢 :如果兩個(gè)用戶離線編輯了很長(zhǎng)時(shí)間,重新連接時(shí)需要轉(zhuǎn)換大量操作,性能很差。



四.RGA:一種經(jīng)典的序列 CRDT

CRDT(Conflict-free Replicated Data Type)采用了完全不同的思路: 不是在收到操作后轉(zhuǎn)換它,而是設(shè)計(jì)一種數(shù)據(jù)結(jié)構(gòu),使得無(wú)論操作以什么順序應(yīng)用,結(jié)果都相同 。這就像設(shè)計(jì)一種特殊的“加法”——無(wú)論你按什么順序把數(shù)字加起來(lái),結(jié)果都一樣。數(shù)學(xué)上,這要求操作滿足 交換律 和 結(jié)合律 。

1、RGA:一種經(jīng)典的序列 CRDT

RGA(Replicated Growable Array)是 2011 年提出的一種序列 CRDT,專門用于解決協(xié)同文本編輯中的沖突問(wèn)題。它的核心思想很簡(jiǎn)單: 用相對(duì)位置代替絕對(duì)位置 。


還是用 Alice 和 Bob 的例子。初始文檔是 AB ,Alice 和 Bob 同時(shí)在位置 1 插入字符——Alice 插入 X ,Bob 插入 Y 。

OT 的做法是調(diào)整位置坐標(biāo)。但 RGA 換了個(gè)思路: 不用數(shù)字位置,用“插在誰(shuí)后面”來(lái)描述插入點(diǎn) 。

具體來(lái)說(shuō):

  • Alice 的操作不再是“在位置 1 插入 X”,而是“在 A 后面插入 X”

  • Bob 的操作是“在 A 后面插入 Y”

兩個(gè)操作都想插在 A 后面,怎么辦?RGA 給每個(gè)字符分配一個(gè) 全局唯一的 ID 。這個(gè) ID 由兩部分組成:

  • 用戶 ID :每個(gè)用戶有一個(gè)唯一標(biāo)識(shí)(如 Alice 是 A ,Bob 是 B )

  • 本地計(jì)數(shù)器 :每個(gè)用戶維護(hù)一個(gè)遞增的計(jì)數(shù)器,每次插入新字符時(shí) +1

所以 A@1 表示“Alice 的第 1 個(gè)操作”, B@1 表示“Bob 的第 1 個(gè)操作”。當(dāng)兩個(gè)字符想插入同一位置時(shí),比較 ID 來(lái)決定順序——先比本地計(jì)數(shù)器,計(jì)數(shù)器相同時(shí)再比用戶 ID(作為 tie-breaker)。這里兩個(gè)計(jì)數(shù)器都是 1,所以比較用戶 ID: B > A ,因此 B@1 排在 A@1 前面,結(jié)果就是 A → Y → X → B ,即 AYXB 。

如果用 MoonBit 實(shí)現(xiàn),我們可以先定義每個(gè)節(jié)點(diǎn)的類型和它的 compare 規(guī)則:

/// 唯一標(biāo)識(shí)符
struct ID {
peer : UInt64 // 用戶 ID
counter : Int // 本地計(jì)數(shù)器
} derive(Eq)


/// 比較兩個(gè) ID,用于解決并發(fā)插入沖突
impl Compare for ID with compare(self, other) {
// 先比較 counter,再比較 peer(打破平局)
if self.counter != other.counter {
other.counter - self.counter
} else if self.peer > other.peer { -1 }
else if self.peer < other.peer { 1 }
else { 0 }
}

插入時(shí),在目標(biāo)位置之后找到正確的插入點(diǎn)——跳過(guò)所有 ID 更大的節(jié)點(diǎn):

/// 在 target 之后插入,返回插入位置
fn find_insert_pos(order : Array[ID], target_pos : Int, new_id : ID) -> Int {
let mut pos = target_pos + 1
while pos < order.length() && new_id.compare(order[pos]) > 0 {
pos = pos + 1 // new_id 更小,繼續(xù)往后找
}
pos
}

我們剛才假設(shè)了只有插入的情況,對(duì)于刪除問(wèn)題,RGA 采用墓碑(Tombstone)策略:刪除字符時(shí)不真正移除,只標(biāo)記為“已刪除”。

為什么不能真刪除?考慮這個(gè)場(chǎng)景:Alice 刪除了 B,同時(shí) Bob(還沒(méi)收到刪除)在 B 后面插入 X。如果 B 真的沒(méi)了,Bob 的“在 B 后面插入”就找不到參照物了。墓碑讓 B 保留在數(shù)據(jù)結(jié)構(gòu)中,只是渲染時(shí)跳過(guò),這樣 Bob 的操作仍然有效。

/// RGA 節(jié)點(diǎn)
struct RGANode {
id : ID
char : Char
mut deleted : Bool // 墓碑標(biāo)記
}

/// 刪除:標(biāo)記為墓碑
fn RGANode::delete(self : RGANode) -> Unit {
self.deleted = true
}

/// 渲染:跳過(guò)墓碑
fn render(nodes : Array[RGANode]) -> String {
let sb = StringBuilder::new()
for node in nodes {
if !node.deleted { sb.write_char(node.char) }
}
sb.to_string()
}

在上面的簡(jiǎn)單實(shí)現(xiàn)當(dāng)中,為了更加簡(jiǎn)潔易懂,我們采用的是數(shù)組來(lái)存儲(chǔ) RGA 的節(jié)點(diǎn)。而熟悉數(shù)據(jù)結(jié)構(gòu)的讀者很輕松就可以發(fā)現(xiàn):RGA 會(huì)存在頻繁的插入情況,因此鏈表也許更適配這種算法。而實(shí)際的工程中則經(jīng)常使用更加穩(wěn)健高效的結(jié)構(gòu)如 B+ Tree 或跳表實(shí)現(xiàn)它。

2、RGA 的問(wèn)題

RGA 解決了并發(fā)沖突問(wèn)題,不需要中央服務(wù)器,支持 P2P 同步,但它也有顯著的缺點(diǎn):

  • 元數(shù)據(jù)膨脹 :每個(gè)字符都需要存儲(chǔ) ID(工程上很容易達(dá)到 16+ 字節(jié))和前驅(qū)引用,一篇 10 萬(wàn)字的文檔,元數(shù)據(jù)可能比內(nèi)容還大。

  • 墓碑累積 :刪除的字符永遠(yuǎn)保留在內(nèi)存中。一篇編輯多次的文檔,可能 90% 的數(shù)據(jù)都是墓碑,而且文字上可能還有其他維度,比如富文本,會(huì)進(jìn)一步加劇這個(gè)缺點(diǎn)造成的影響。

  • 加載緩慢 :從磁盤(pán)加載文檔時(shí),需要重建整個(gè)數(shù)據(jù)結(jié)構(gòu),這是 O(n) 甚至 O(n log n) 的操作。



五.Event Graph Walker:更好的方案
1、原理介紹

Event Graph Walker(簡(jiǎn)稱 Eg-walker)是由 Joseph Gentle 和 Martin Kleppmann 在 2024 年提出的新 CRDT 算法。

前面我們看到,OT 操作簡(jiǎn)單(只有位置索引)但需要中央服務(wù)器;CRDT 支持 P2P 但元數(shù)據(jù)膨脹嚴(yán)重。Eg-walker 的核心洞察是:兩者可以結(jié)合,即存儲(chǔ)時(shí)用簡(jiǎn)單索引,合并時(shí)臨時(shí)構(gòu)建 CRDT。

操作像 OT 一樣輕量,只記錄 insert(pos, char) 和 delete(pos) 。需要合并并發(fā)操作時(shí),臨時(shí)重放歷史、構(gòu)建 CRDT 狀態(tài)來(lái)解決沖突,合并完就丟掉。

可能很多讀者會(huì)這種“臨時(shí)構(gòu)建 CRDT 解決問(wèn)題的方式”存在一些性能方面的顧慮,我們的確要承認(rèn)雖然臨時(shí)構(gòu)建確實(shí)有開(kāi)銷,但是由于大部分時(shí)間并不需要 CRDT 參與編輯工作,只有同步并發(fā)編輯的時(shí)候才需要,而且 Eg-Walker 的性質(zhì)很明顯支持增量構(gòu)建與局部構(gòu)建,只需要從快照構(gòu)建或者再?zèng)_突區(qū)域構(gòu)建 CRDT 解決沖突即可。而且可以設(shè)想的是,在操作歷史越來(lái)越復(fù)雜的情況下,臨時(shí)構(gòu)建會(huì)比維護(hù)一個(gè)會(huì)一直增長(zhǎng)的結(jié)構(gòu)更加穩(wěn)健高效。


2、代碼實(shí)現(xiàn) 1)基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)

首先是操作的定義。與 RGA 使用“在某個(gè) ID 后面插入”的相對(duì)定位不同,Eg-walker 直接使用數(shù)字位置索引,就像 OT 一樣簡(jiǎn)單:

enum SimpleOp {
Insert(Int, String) // Insert(位置, 內(nèi)容)
Delete(Int, Int) // Delete(位置, 長(zhǎng)度)
}

接下來(lái)是 事件(Event) 的定義。事件是對(duì)操作的包裝,添加了因果關(guān)系信息:

struct Event {
id : ID // 唯一標(biāo)識(shí)符
deps : Array[ID] // 依賴的事件(父節(jié)點(diǎn))
op : SimpleOp // 實(shí)際的操作內(nèi)容
lamport : Int // Lamport 時(shí)間戳,用于排序
}

然后我們就可以根據(jù)他們定義出一個(gè)事件圖(Event Graph):

struct EventGraph {
events : Map[ID, Event] // 所有已知事件
frontiers : Array[ID] // 當(dāng)前最新的事件 ID 集合
}

這里定義中的 frontiers 記錄了“當(dāng)前版本”——那些沒(méi)有被任何其他事件依賴的事件。如果讀者熟悉 Git 的一些概念,那么可以把它理解為 Git 中當(dāng)前所有分支的 HEAD 指針集合。

2)添加事件與維護(hù) Frontier

當(dāng)收到新事件時(shí),除了將事件存入當(dāng)前的事件表中,還需要更新 frontier。由于 frontier 記錄的是“沒(méi)有后續(xù)事件的事件”,當(dāng)新事件依賴某個(gè)舊 head 時(shí),說(shuō)明這個(gè)舊 head 已經(jīng)有了后續(xù),不再是“最新的”了,需要從 frontier 中移除,然后把新事件加入 frontier。

fn EventGraph::add_event(self : EventGraph, event : Event) -> Unit {
self.events[event.id] = event
self.frontiers = self.heads.retain(frontier => !event.deps.contains(frontier))
self.frontiers.push(event.id)
}
3)LCA(最近公共祖先) 與拓?fù)渑判?/p>

合并兩個(gè)版本需要解決兩個(gè)問(wèn)題:

1、找到分叉點(diǎn)(在 Event Graph 上找到 LCA ) :確定從哪里開(kāi)始重放

2、確定重放順序(根據(jù) Lamport 拓?fù)渑判?) :按因果關(guān)系排序事件

這兩部分都屬于比較基本的圖論問(wèn)題,相信讀者在查閱資料后可以很快的實(shí)現(xiàn)出來(lái)。不過(guò)需要注意的是,在工業(yè)實(shí)現(xiàn) Eg-Walker 算法時(shí),我們通常不使用常規(guī)介紹的算法求 LCA,而是對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行改進(jìn),應(yīng)用一些緩存機(jī)制來(lái)提高效率。

4)合并算法

現(xiàn)在我們有了所有組件,可以實(shí)現(xiàn)完整的合并算法了:

fn EventGraph::merge(
self : EventGraph,
local_frontiers : Array[ID],
remote_frontiers : Array[ID], // 遠(yuǎn)程 peer 的 frontiers,隨事件一起發(fā)送
remote_events : Array[Event]
) -> String {
// 步驟 1:將遠(yuǎn)程事件添加到事件圖
for event in remote_events {
self.add_event(event)
}
// 步驟 2:找到本地版本和遠(yuǎn)程版本的 LCA(用 VersionVector 取交集)
let lca = self.find_lca(local_frontiers, remote_frontiers)
// 步驟 4:收集從 LCA 到兩個(gè)分支的所有事件
let events_to_replay = self.collect_events_after(lca)
// 步驟 5:按 Lamport 時(shí)間戳拓?fù)渑判?br/> let sorted = self.topological_sort(events_to_replay)
// 步驟 6:創(chuàng)建臨時(shí) RGA,重放所有事件
let temp_rga = RGA::new()
for event in sorted {
self.apply_to_rga(temp_rga, event)
}
// 步驟 7:返回最終文本,丟棄臨時(shí) RGA
temp_rga.to_string()
}

合并流程可以總結(jié)為三個(gè)階段:

  • Retreat(回退) :找到 LCA,確定需要重放的事件范圍

  • Collect(收集) :收集兩個(gè)分支上的所有事件,按 Lamport 時(shí)間戳拓?fù)渑判?/p>

  • Advance(推進(jìn)) :創(chuàng)建臨時(shí) RGA,按順序重放所有事件,用 CRDT 解決沖突


六.Lomo 與開(kāi)發(fā)一個(gè)協(xié)作文本編輯器
1、什么是 Loro/Lomo

Loro 是一個(gè)基于 Eg-walker 算法的高性能 CRDT 庫(kù),由 Rust 實(shí)現(xiàn)。它支持多種數(shù)據(jù)類型(文本、列表、Map、可移動(dòng)列表、樹(shù)結(jié)構(gòu)等),提供豐富的協(xié)作功能,被用于構(gòu)建實(shí)時(shí)協(xié)作應(yīng)用。而 Lomo 是 Loro 的 MoonBit 移植版本,與 Loro Rust 版本保持二進(jìn)制兼容,這意味著用 lomo 生成的文檔可以被 Loro 讀取,反之亦然。

Lomo 的核心 API 非常簡(jiǎn)潔:

let doc = LoroDoc::new()
doc.set_peer_id(1UL)
// 獲取文本容器并編輯
let text = doc.get_text("content")
doc.text_insert(text, 0, "Hello, World!")
doc.text_delete(text, 5, 2)
// 導(dǎo)出更新(用于同步)
let updates = doc.export_updates()
// 另一個(gè) peer 導(dǎo)入更新
let doc2 = LoroDoc::new()
doc2.set_peer_id(2UL)
doc2.import_updates(updates) // 兩邊內(nèi)容自動(dòng)同步

2、做一個(gè)協(xié)同文本編輯器

因?yàn)閰f(xié)同需求經(jīng)常發(fā)生在前端,因此 Loro 發(fā)行了 Wasm API 以保證前端也可以使用這一優(yōu)秀的 CRDTs 庫(kù)。但 Rust 編譯的 Wasm 體積偏大,而且難以根據(jù)用戶某一項(xiàng)單獨(dú)需求進(jìn)行 tree-sharking,因此成為很多前端開(kāi)發(fā)者使用 Loro 的痛點(diǎn)。

但前端如果使用 MoonBit+Lomo 在 JavaScript 后端編寫(xiě),則編譯器只會(huì)按需編譯 API,最終編譯結(jié)果非常好。同時(shí),MoonBit 的 Wasm 編譯結(jié)果往往會(huì)更小、更干凈,就算是使用 Wasm 后端進(jìn)行發(fā)行也會(huì)得到很好的效果。

因此我們可以嘗試根據(jù) JavaScript 后端制作一個(gè)協(xié)同文本編輯器來(lái)驗(yàn)證這一點(diǎn),下面展示了大致的實(shí)現(xiàn)方式:

首先在 MoonBit 一側(cè)封裝文檔操作,供 JavaScript 調(diào)用:

///| 創(chuàng)建文檔
pub fn create_doc(peer_id : Int) -> Int {
let doc = LoroDoc::new()
doc.set_peer_id(peer_id.to_uint64())
let text = doc.get_text("body")
// 訂閱本地更新,自動(dòng)收集待發(fā)送的數(shù)據(jù)
let _ = doc.subscribe_local_update((bytes) => {
pending_updates.push(bytes)
true
}
// ...
}


///| 應(yīng)用編輯操作
pub fn apply_edit_utf16(doc_id : Int, start : Int, delete_len : Int, insert_text : String) -> Bool {
let doc = docs[doc_id]
let text = texts[doc_id]
if delete_len > 0 { doc.text_delete_utf16(text, start, delete_len)? }
if insert_text.length() > 0 { doc.text_insert_utf16(text, start, insert_text)? }
true
}

JavaScript 側(cè)處理用戶輸入和同步邏輯:

// 處理用戶輸入
function handleInput(side, other) {
const nextText = side.el.textContent;
const change = diffText(side.text, nextText); // 計(jì)算新舊文本的差異
// 應(yīng)用到 CRDT(調(diào)用 MoonBit 導(dǎo)出的函數(shù))
apply_edit_utf16(side.id, change.start, change.deleteCount, change.insertText);
side.text = nextText;
syncFrom(side, other); // 同步給另一方
}


// 同步邏輯
function syncFrom(from, to) {
const updates = drain_updates(from.id); // 獲取待發(fā)送的更新(MoonBit 導(dǎo)出)
if (state.online) {
apply_updates(to.id, updates); // 在線:立即應(yīng)用(MoonBit 導(dǎo)出)
} else {
from.outbox.push(...updates); // 離線:緩存到發(fā)件箱
}
}

最終經(jīng)過(guò)一些樣式編寫(xiě)和頁(yè)面編寫(xiě)的工作,我們就可以得到一個(gè)基于 CRDTs 的協(xié)同編輯器:


該項(xiàng)目的源碼在文章末尾已經(jīng)給出,感興趣的讀者可以自行參考并開(kāi)發(fā)更有意思的項(xiàng)目。

七.總結(jié)

本文從并發(fā)沖突問(wèn)題出發(fā),介紹了實(shí)時(shí)協(xié)作算法的演進(jìn):

  • OT :通過(guò)轉(zhuǎn)換操作解決沖突,但需要中央服務(wù)器

  • RGA :用唯一 ID 和相對(duì)位置實(shí)現(xiàn)去中心化,但元數(shù)據(jù)膨脹

  • Eg-walker:結(jié)合兩者優(yōu)點(diǎn),存儲(chǔ)簡(jiǎn)單操作,合并時(shí)臨時(shí)構(gòu)建 CRDT

我們用 MoonBit 實(shí)現(xiàn)了上述算法的核心數(shù)據(jù)結(jié)構(gòu)與關(guān)鍵計(jì)算部分、還介紹了 Loro/lomo 庫(kù)和他們的基本使用,并使用 Lomo 開(kāi)發(fā)了一個(gè)簡(jiǎn)單的協(xié)作編輯應(yīng)用。

從 1989 年 OT 的誕生,到 2011 年 RGA 等 CRDT 的形式化,再到 2024 年 Eg-walker 的創(chuàng)新融合,實(shí)時(shí)協(xié)作算法經(jīng)歷了三十余年的演進(jìn)。而近年來(lái)隨著 Local-first 理念的興起,CRDT 正從學(xué)術(shù)論文走向生產(chǎn)實(shí)踐——Figma、Linear 背后都有它的身影。

未來(lái),歷史壓縮、復(fù)雜數(shù)據(jù)結(jié)構(gòu)、端到端加密等方向仍在快速推進(jìn);MoonBit 高效編譯到 WebAssembly 的能力,也為 CRDTs 在瀏覽器和邊緣設(shè)備上的部署提供了新可能。

八.參考項(xiàng)目/文獻(xiàn)

Lomo-Demo(編輯器)演示:

https://lampese.github.io/lomo-demo/

Lomo-Demo(編輯器)源碼:

https://github.com/Lampese/lomo-demo

Loro:https://loro.dev/

Lomo:https://github.com/Lampese/lomo

Eg-walker 論文:

https://arxiv.org/abs/2409.14252

聲明:包含AI生成內(nèi)容

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
震驚!網(wǎng)傳廣西某設(shè)計(jì)院普通員工年終獎(jiǎng)144000元,月工資86699元

震驚!網(wǎng)傳廣西某設(shè)計(jì)院普通員工年終獎(jiǎng)144000元,月工資86699元

火山詩(shī)話
2026-02-27 12:08:36
郭書(shū)瑤東京吃拉面「突亮出奇葩私物」!友秒吐槽:有病哦 對(duì)話全曝光

郭書(shū)瑤東京吃拉面「突亮出奇葩私物」!友秒吐槽:有病哦 對(duì)話全曝光

ETtoday星光云
2026-02-26 13:50:05
米蘭這一晚,34歲的肖戰(zhàn)讓內(nèi)娛見(jiàn)識(shí)到了什么叫:世界級(jí)巨星的排面

米蘭這一晚,34歲的肖戰(zhàn)讓內(nèi)娛見(jiàn)識(shí)到了什么叫:世界級(jí)巨星的排面

白宸侃片
2026-02-28 08:36:24
中國(guó)駐伊朗大使館:鄭重提醒在伊中國(guó)公民密切關(guān)注安全形勢(shì)變化

中國(guó)駐伊朗大使館:鄭重提醒在伊中國(guó)公民密切關(guān)注安全形勢(shì)變化

澎湃新聞
2026-02-28 03:49:02
高市真正反省涉臺(tái)謬論了嗎?人民網(wǎng)刊文九問(wèn)日本

高市真正反省涉臺(tái)謬論了嗎?人民網(wǎng)刊文九問(wèn)日本

澎湃新聞
2026-02-27 17:25:03
74歲陳凱歌在三亞豪宅過(guò)年,穿5萬(wàn)元皮鞋戴大金表,臉上有老年斑

74歲陳凱歌在三亞豪宅過(guò)年,穿5萬(wàn)元皮鞋戴大金表,臉上有老年斑

洲洲影視娛評(píng)
2026-02-26 13:52:42
美媒:20歲華裔選手粉絲數(shù)遠(yuǎn)超谷愛(ài)凌 她拒絕中國(guó)招募 對(duì)美國(guó)忠誠(chéng)

美媒:20歲華裔選手粉絲數(shù)遠(yuǎn)超谷愛(ài)凌 她拒絕中國(guó)招募 對(duì)美國(guó)忠誠(chéng)

念洲
2026-02-25 11:46:11
老百姓沒(méi)等來(lái)房?jī)r(jià)如蔥,12%的房產(chǎn)稅、20%的“遺產(chǎn)稅”,已經(jīng)開(kāi)始

老百姓沒(méi)等來(lái)房?jī)r(jià)如蔥,12%的房產(chǎn)稅、20%的“遺產(chǎn)稅”,已經(jīng)開(kāi)始

貓叔東山再起
2026-02-27 10:50:03
1比4慘??!28歲陳幸同狀態(tài)低迷,中國(guó)女單主力亟需調(diào)整提升

1比4慘?。?8歲陳幸同狀態(tài)低迷,中國(guó)女單主力亟需調(diào)整提升

卿子書(shū)
2026-02-28 09:51:11
連續(xù)5年歐冠淘汰賽相遇,曼城總監(jiān):與皇馬的比賽像決賽一樣

連續(xù)5年歐冠淘汰賽相遇,曼城總監(jiān):與皇馬的比賽像決賽一樣

大眼瞄世界
2026-02-28 09:53:39
夸美國(guó)空氣香甜的楊舒平,已被美驅(qū)逐出境,如今回國(guó)下場(chǎng)怎么樣了

夸美國(guó)空氣香甜的楊舒平,已被美驅(qū)逐出境,如今回國(guó)下場(chǎng)怎么樣了

談史論天地
2026-02-07 13:20:03
“農(nóng)村太子爺含金量堪比兩斤雞屎!”6個(gè)姐姐給弟弟征婚,被群嘲

“農(nóng)村太子爺含金量堪比兩斤雞屎!”6個(gè)姐姐給弟弟征婚,被群嘲

妍妍教育日記
2026-02-26 19:52:39
新疆24歲產(chǎn)婦誕下5胞胎,體重最輕的870克,網(wǎng)友:補(bǔ)貼拿到手軟了

新疆24歲產(chǎn)婦誕下5胞胎,體重最輕的870克,網(wǎng)友:補(bǔ)貼拿到手軟了

云舟史策
2026-02-27 23:22:43
多省份公布2025年人口數(shù)據(jù)

多省份公布2025年人口數(shù)據(jù)

第一財(cái)經(jīng)資訊
2026-02-27 16:40:59
廣東宏遠(yuǎn)新外援?身高2米18的NBA落選秀,單場(chǎng)21分23籃板

廣東宏遠(yuǎn)新外援?身高2米18的NBA落選秀,單場(chǎng)21分23籃板

籃球看比賽
2026-02-27 13:59:20
搶完中企資產(chǎn),再搜查辦公室,巴當(dāng)局闖下大禍,中國(guó)準(zhǔn)備甩出王牌

搶完中企資產(chǎn),再搜查辦公室,巴當(dāng)局闖下大禍,中國(guó)準(zhǔn)備甩出王牌

觀察者海風(fēng)
2026-02-27 23:21:57
司機(jī)接180元獨(dú)享取消60元小單,乘客破防大罵,司機(jī)回復(fù)太真實(shí)!

司機(jī)接180元獨(dú)享取消60元小單,乘客破防大罵,司機(jī)回復(fù)太真實(shí)!

網(wǎng)約車觀察室
2026-02-28 09:52:37
WTT大滿貫!女單4強(qiáng)對(duì)陣出爐,張本美和強(qiáng)勢(shì)橫掃,王曼昱苦戰(zhàn)逆轉(zhuǎn)

WTT大滿貫!女單4強(qiáng)對(duì)陣出爐,張本美和強(qiáng)勢(shì)橫掃,王曼昱苦戰(zhàn)逆轉(zhuǎn)

削桐作琴
2026-02-27 18:12:24
蒙古國(guó)的人,為啥如此仇視中國(guó)人?

蒙古國(guó)的人,為啥如此仇視中國(guó)人?

賤議你讀史
2026-02-27 15:12:56
防長(zhǎng)剛在日本開(kāi)完會(huì),馬來(lái)西亞對(duì)南海亮明立場(chǎng),將無(wú)視中方的主張

防長(zhǎng)剛在日本開(kāi)完會(huì),馬來(lái)西亞對(duì)南海亮明立場(chǎng),將無(wú)視中方的主張

安逸安逸
2026-02-28 09:56:15
2026-02-28 10:32:49
開(kāi)源中國(guó) incentive-icons
開(kāi)源中國(guó)
每天為開(kāi)發(fā)者推送最新技術(shù)資訊
7602文章數(shù) 34502關(guān)注度
往期回顧 全部

科技要聞

狂攬1100億美元!OpenAI再創(chuàng)融資神話

頭條要聞

牛彈琴:伊朗面臨生死存亡關(guān)鍵時(shí)刻 信號(hào)已經(jīng)很明顯了

頭條要聞

牛彈琴:伊朗面臨生死存亡關(guān)鍵時(shí)刻 信號(hào)已經(jīng)很明顯了

體育要聞

一場(chǎng)必須要贏的比賽,男籃何止擊敗了裁判

娛樂(lè)要聞

郭晶晶霍啟剛現(xiàn)身香港藝術(shù)節(jié)盡顯恩愛(ài)

財(cái)經(jīng)要聞

沈明高提共富建議 百姓持科技股國(guó)家兜底

汽車要聞

嵐圖泰山黑武士版3月上市 搭載華為四激光智駕方案

態(tài)度原創(chuàng)

本地
家居
數(shù)碼
旅游
軍事航空

本地新聞

津南好·四時(shí)總相宜

家居要聞

素色肌理 品意式格調(diào)

數(shù)碼要聞

蘋(píng)果OLED版iPad Mini即將發(fā)布 或?qū)⒊蔀镵indle殺手?

旅游要聞

街頭巷尾忽如雪!觀山湖:被櫻花悄悄寫(xiě)成了詩(shī)

軍事要聞

美國(guó)11架F-22隱形戰(zhàn)機(jī)抵達(dá)以色列

無(wú)障礙瀏覽 進(jìn)入關(guān)懷版