<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>协作编辑 | 锤子前端</title><description>Now vibe coding, so learning hammer FE ?</description><link>https://channel.meo-ai.com</link><item><title>《Notion如何用CRDT解决并发编辑冲突》</title><link>https://channel.meo-ai.com/posts/711</link><guid isPermaLink="true">https://channel.meo-ai.com/posts/711</guid><pubDate>Thu, 24 Sep 2026 12:31:04 GMT</pubDate><content:encoded>&lt;span class=&quot;post-title-source&quot;&gt;《Notion如何用CRDT解决并发编辑冲突》&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;标签：&lt;br /&gt;&lt;a href=&quot;/search/result?q=%23%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F&quot; title=&quot;#分布式系统&quot;&gt;#分布式系统&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23%E5%8D%8F%E5%90%8C%E7%BC%96%E8%BE%91&quot; title=&quot;#协同编辑&quot;&gt;#协同编辑&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23CRDT%E7%AE%97%E6%B3%95&quot; title=&quot;#CRDT算法&quot;&gt;#CRDT算法&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23%E6%95%B0%E6%8D%AE%E4%B8%80%E8%87%B4%E6%80%A7&quot; title=&quot;#数据一致性&quot;&gt;#数据一致性&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;总结：&lt;br /&gt;&lt;br /&gt;文章要点：&lt;br /&gt;&lt;br /&gt;1. Notion在2025年重新设计了底层文本编辑系统，从&quot;最后写入获胜&quot;(LWW)模式转向基于CRDT的并发编辑方案，解决了多人同时编辑同一区块时的数据丢失问题。&lt;br /&gt;&lt;br /&gt;2. CRDT(无冲突复制数据类型)允许多个客户端保留本地数据副本，并以确定性方式合并同时发生的更改，确保不会丢失任何人的修改。&lt;br /&gt;&lt;br /&gt;3. Notion使用的CRDT基于经典的RGA(可复制增长数组)序列CRDT，这是一个树形数据结构，每个字符都有唯一且稳定的ID，插入和删除操作都引用这些ID。&lt;br /&gt;&lt;br /&gt;4. 删除操作采用&quot;墓碑&quot;机制——标记项目为已删除但保留在树中，因为可能有在途或离线操作依赖于已删除字符的ID。&lt;br /&gt;&lt;br /&gt;5. 为提升存储效率，Notion将连续字符分组，为整组字符分配一个ID并存储运行长度，而不是为每个字符单独分配ID。&lt;br /&gt;&lt;br /&gt;6. 支持富文本格式需要解决注释冲突，Notion引入了基于Peritext算法的操作，支持可扩展和不可扩展的注释类型(如粗体vs超链接)。&lt;br /&gt;&lt;br /&gt;7. Notion的区块模型带来了独特挑战：当用户按下回车键分割区块时，需要处理文本在区块间移动时的并发编辑问题。&lt;br /&gt;&lt;br /&gt;8. 为解决这一问题，Notion引入了&quot;文本切片&quot;概念——每个区块的文本项属于一个文本切片，分割区块时切片也会相应分割并移动到新区块。&lt;br /&gt;&lt;br /&gt;9. 每个文本项ID由会话ID和Lamport时钟组成，确保ID的唯一性；指向同一原点的项目按逻辑时间戳排序，会话ID作为平局决胜因素。&lt;br /&gt;&lt;br /&gt;URL：&lt;br /&gt;&lt;a href=&quot;https://www.notion.com/blog/how-notion-handles-concurrent-editing-with-crdts&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; title=&quot;https://www.notion.com/blog/how-notion-handles-concurrent-editing-with-crdts&quot;&gt;https://www.notion.com/blog/how-notion-handles-concurrent-editing-with-crdts&lt;/a&gt;&lt;a class=&quot;tgme_widget_message_link_preview&quot; href=&quot;https://notion.com/blog/how-notion-handles-concurrent-editing-with-crdts&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; title=&quot;Building a CRDT-based rich-text system that merges concurrent edits across Notion blocks—without losing anyone’s work&quot;&gt;
  
  &lt;div class=&quot;link_preview_site_name accent_color&quot;&gt;Notion&lt;/div&gt;
  &lt;img class=&quot;link_preview_image&quot; alt=&quot;How Notion handles concurrent editing with CRDTs&quot; src=&quot;/static/https://cdn4.telesco.pe/file/q84q8yLEOOmLTc0ofDVh85lGSkkH34LEWNUWMrHuBfa8DMVFJ70uPJOOE91WEi10t1DrhmFYqsXCh1NfU5hDlqL6-yqn4KkduyVHu_oxyCo84ZKtV4pGmbLs6tebPyW48imzpJhD0zBjXh0zjXYpH24aeEqdBxnY-baWgrjztdYEW1OCTR6C8sUFD3sE_7GA_YIMdh1-n2XV41pkqbnZCulJHntHA5-HoW6BP4SjHzBORFYzALteREU5YTaZQdwxavRRotbEdDRUxd9Gt1HRzT1Xk1zPBdCs5HUxAupip30-MXf3AHX9kObTW78Rco26_apNkgmvHdx0OvySIBASAw.jpg&quot; width=&quot;1200&quot; height=&quot;630&quot; loading=&quot;eager&quot; /&gt;
  &lt;div class=&quot;link_preview_title&quot;&gt;How Notion handles concurrent editing with CRDTs&lt;/div&gt;
  &lt;div class=&quot;link_preview_description&quot;&gt;Building a CRDT-based rich-text system that merges concurrent edits across Notion blocks—without losing anyone’s work&lt;/div&gt;
&lt;/a&gt;</content:encoded></item><item><title>《关于协作编辑的谎言（第二部分）：为什么我们不用Yjs》</title><link>https://channel.meo-ai.com/posts/575</link><guid isPermaLink="true">https://channel.meo-ai.com/posts/575</guid><pubDate>Wed, 18 Mar 2026 01:39:20 GMT</pubDate><content:encoded>&lt;span class=&quot;post-title-source&quot;&gt;《关于协作编辑的谎言（第二部分）：为什么我们不用Yjs》&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;标签：&lt;a href=&quot;/search/result?q=%23%E5%89%8D%E7%AB%AF&quot; title=&quot;#前端&quot;&gt;#前端&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23ProseMirror&quot; title=&quot;#ProseMirror&quot;&gt;#ProseMirror&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23CRDT&quot; title=&quot;#CRDT&quot;&gt;#CRDT&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23%E5%8D%8F%E4%BD%9C%E7%BC%96%E8%BE%91&quot; title=&quot;#协作编辑&quot;&gt;#协作编辑&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96&quot; title=&quot;#性能优化&quot;&gt;#性能优化&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23Yjs&quot; title=&quot;#Yjs&quot;&gt;#Yjs&lt;/a&gt; &lt;a href=&quot;/search/result?q=%23%E5%AE%9E%E6%97%B6%E5%8D%8F%E4%BD%9C&quot; title=&quot;#实时协作&quot;&gt;#实时协作&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;总结：&lt;br /&gt;本文是Moment.dev团队关于协作编辑算法分析的第二部分，作者详细阐述了为何在生产环境中放弃Yjs而选择基于ProseMirror-collab的简单方案。文章指出Yjs存在严重的性能问题（每次协作编辑会销毁重建整个文档）、与文档Schema冲突、权限控制困难、调试困难以及墓碑数据占用内存等问题。作者认为，除非真正需要无主节点的P2P架构，否则40行代码的&quot;简单方案&quot;在性能、可维护性和开发体验上都优于复杂的CRDT实现。&lt;br /&gt;&lt;br /&gt;文章要点：&lt;br /&gt;- Yjs存在严重性能缺陷：每次协作编辑会销毁并重建整个文档，导致60fps目标难以达成，影响NodeView、插件状态、撤销功能和光标位置管理&lt;br /&gt;- 简单方案仅需40行代码：使用prosemirror-collab库，通过单一权威节点管理文档版本和事务，支持乐观更新、离线编辑和网络中断恢复&lt;br /&gt;- Yjs与文档Schema冲突：在无主节点架构下难以验证事务有效性，可能导致数据永久丢失，升级时尤其危险&lt;br /&gt;- 权限控制复杂化：需要将Yjs的XML更新预测转换为ProseMirror事务来判断权限，实现难度大&lt;br /&gt;- 墓碑数据问题：Yjs需保留删除标记，导致内存持续增长或数据丢失风险，而简单方案通过数据库存储步骤即可解决&lt;br /&gt;- 调试困难：CRDT仅保证最终一致性，难以区分暂时分歧与真正错误，调试工具受限&lt;br /&gt;- 核心观点：技术选型应从最终用户体验出发，而非算法本身；如无P2P刚需，简单方案在各方面均优于CRDT&lt;br /&gt;&lt;br /&gt;文章URL：&lt;a href=&quot;https://www.moment.dev/blog/lies-i-was-told-pt-2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; title=&quot;https://www.moment.dev/blog/lies-i-was-told-pt-2&quot;&gt;https://www.moment.dev/blog/lies-i-was-told-pt-2&lt;/a&gt;&lt;a class=&quot;tgme_widget_message_link_preview&quot; href=&quot;https://moment.dev/blog/lies-i-was-told-pt-2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
  
  &lt;div class=&quot;link_preview_site_name accent_color&quot;&gt;Lies I was Told About Collaborative Editing, Part 2: Why we don&apos;t use Yjs / Moment devlog&lt;/div&gt;
  &lt;img class=&quot;link_preview_image&quot; alt=&quot;Lies I was Told About Collaborative Editing, Part 2: Why we don&apos;t use Yjs / Moment devlog&quot; src=&quot;/static/https://cdn4.telesco.pe/file/YVXaUzBE8-9TDW2QQrSSbabfgg71zJ4YfK9str6-S1LPODRrO0GTgZm9XVC005_t5HR8VqdNrsgcUwQyA9CcsGyd1JTNXiYmfD35KPvxoWVvTV3w40qwfsqy8doKw0ZtWIufS8kkP6b_7C_qBXZmPDelkDueKKd_mZLaVGpRdnWPevjv76nE543DoXGcMtepNx9ppudeaLhaphSNg-17nX4wJVoKz43YqT9z_ynPXioKsnRqKvzAi1NxlO07pXRzyhwn5GcDxgfJ6WE6NlLa5PhPeeJh7VLRKBwCq1-crT8pqRc_IVTVDnEToydSWbK2EBXIWObDBA27HcLh3qeT-Q.jpg&quot; width=&quot;1200&quot; height=&quot;630&quot; loading=&quot;eager&quot; /&gt;
  
  
&lt;/a&gt;</content:encoded></item></channel></rss>