Notion CRDT系统设计评测对谷歌L5工程师性能数据

一句话总结

Notion的CRDT系统设计评测这道题,表面考的是分布式数据一致性,实际测的是你对"工程权衡"的直觉。谷歌L5面试不是要你背诵OT与CRDT的理论差异,而是要你在15分钟内让面试官相信:你能在延迟、冲突解决、存储开销三者的绞杀中,做出可落地的选择。

大多数候选人死在"炫技式深度"——把CRDT讲成学术论文,却讲不清为什么Notion选了Yjs而不是Automerge,讲不清为什么区块级CRDT比字符级更适合文档场景。正确的判断是:这道题的黄金解法,是把CRDT当作产品决策来论证,而非当作算法题来推导。


适合谁看

正在备战谷歌L5系统设计面试的工程师,尤其是把"性能数据"当作benchmark数字来背的候选人。

三类人最需要校准判断:第一,从中小厂跳大厂的Senior Engineer,你们习惯的是"把需求做完",不是"在约束条件下论证为什么不做完";第二,算法背景强但工程经验浅的候选人,你们容易把CRDT的数学优美性当成得分点,殊不知面试官在等的是"你什么时候发现这条路径走不通";

第三,正在对比Notion、Figma、Google Docs三家实时协作产品技术选型的Tech Lead,你们需要的不只是技术细节,而是"为什么这家公司在这个时间做了这个选择"的决策链条。

不适合的人群也有明确边界:如果你还在问"CRDT是什么"或者"L5和L4面试区别在哪",这篇文章会直接穿透你的认知水位。不是傲慢,而是这类文章的价值在于做裁决,不是补基础。另外,如果你预期通过背诵某本系统设计的"标准答案"就能通过L5,你的备考策略本身就是错的——谷歌L5的bar已经从"知道怎么做"抬升到了"知道什么不能做,且能证明"。

一个具体的筛选信号:如果你在模拟面试中,听到自己说"这里可以用CRDT解决"之后就停下等待面试官认可,你属于需要被这篇文章打断的人。


为什么L5面试把CRDT当成试金石而不是加分项

2019年Notion推出实时协作功能时,业内普遍预期他们会走Google Docs的Operational Transformation路线。结果他们选了Yjs的CRDT实现,这个决策后来被反复拆解。

谷歌L5面试引入这道题,不是要你复现Notion的技术路径,而是要观察你能否识别出:OT与CRDT之争在2019年已经结束了,真正的战场在"区块粒度vs字符粒度"、"中心化服务器vs去中心化同步"、"完整历史保留vs快照压缩"这三组权衡。

一个典型的debrief场景:候选人在白板上画了完整的CRDT状态向量图,解释了YATA算法的合并逻辑,面试官点头,然后在反馈里写"Strong technical depth, lacks product judgment"。另一位候选人只花了3分钟确认"我们假设用户同时编辑同一段落的概率是X",然后花12分钟论证为什么Notion的块级结构天然适合CRDT(每个block有独立ID,冲突域天然隔离),前者进了L4的pool,后者拿到了L5的strong hire。

关键差异不是知识量,而是问题框架:不是"CRDT怎么实现",而是"为什么Notion的问题适合CRDT"。

不是CRDT比OT更先进,而是Notion的产品形态让CRDT的缺陷变得可接受。OT的严格一致性需要中心化服务器做变换,这意味着离线编辑的支持很脆弱;Notion的用例中,移动端弱网环境下的离线优先是核心体验,CRDT的"最终一致性+本地立即响应"正好命中。

但这里藏着陷阱:如果候选人直接跳到"所以CRDT更好",而没有先问"Notion的协作场景里,冲突发生的频率和模式是什么",面试官会标记为"jumped to solution"。正确的节奏是:先定义冲突概率——根据Notion公开的技术博客,他们测过块级冲突率低于0.1%,字符级冲突率高两个数量级——这个数不需要背,但你需要展示"我会先去测这个"的意识。

性能数据的真正考法不是让你报延迟数字。谷歌L5的面试官会追问:"如果Notion要支持1000人同时编辑一个页面,你的CRDT设计会变吗?"这里在测的是你对"复杂度拐点"的敏感度。Yjs的文档级CRDT在50人以下表现线性,超过200人时内存占用和合并计算量会非线性增长。

不是要你记住200这个阈值,而是要你意识到:任何设计都有规模假设,而L5的职责之一就是识别并挑战这些假设。一个拿到strong hire的回答路径:"我会先问这1000人是编辑不同block还是同一块——如果是前者,问题变成block级别的并发控制;如果是后者,可能需要引入操作中转(operation relay)的混合架构,而不是纯CRDT。"这句话的价值不在于方案本身,而在于展示了"不把一个方案套在所有场景"的思维纪律。


> 📖 延伸阅读PM Tool Comparisons: Asana vs Trello vs Notion

性能数据在面试中怎么被使用、怎么被误读

Notion公开过的性能数据极其有限,但散落的技术博客和社区讨论足够拼凑出关键轮廓:初始加载一个10,000 block的页面,Yjs的CRDT状态需要约2MB的内存;单次本地操作的响应延迟在5ms以内;完整历史同步的初始加载时间在中等带宽下约3秒。这些数字在L5面试中的正确用法,不是作为论据支撑你的设计,而是作为"约束条件"来限定你的方案边界。

一个hiring manager在HC(Hiring Committee)上的真实对话摘录:候选人提到了Yjs的2MB开销,然后直接说"这在现代设备上可以忽略"。HM追问:"如果用户在2019年的Android设备上呢?"候选人没有意识到,Notion的CRDT选型中一个被低估的决策点是:他们接受了在低端设备上的性能降级,以换取开发复杂度的降低。

这个trade-off本身比任何具体数字都重要。HM在HC上的原话:"我们需要的是能说出'这里我们愿意牺牲什么'的工程师,不是背诵最优解的人。"

不是性能数据本身重要,而是你对性能数据的"敏感度阈值"重要。L5的期望是:你能区分"这数字好不好"和"这数字对业务意味着什么"。

例如,3秒的初始同步时间在文档场景中是可接受的(用户预期打开文档需要时间),但在实时白板场景(如Figma)中是不可接受的——Figma的CRDT实现采用了不同的序列化策略来压缩初始负载。这个对比不需要你实现过Figma,但需要你在面试中主动构建这种"场景-约束-可接受阈值"的映射。

另一个常被误读的数据点是"冲突解决率"。Notion没有公开过这个指标,但你可以从产品行为反推:当两个用户同时编辑同一个block时,Notion的UI会显示"有人正在编辑"的占位符,而不是等冲突发生后再解决。这不是CRDT的技术特性,而是产品层面对冲突的"预防性设计"。

在面试中,如果你只谈CRDT的合并算法而不谈UI如何减少冲突发生,你的答案是不完整的。面试官在找的是:你能否识别出"技术方案"和"产品方案"的交界地带,并且知道什么时候该把问题推给产品,什么时候必须技术兜底。


L5面试流程拆解:每一轮在测什么、怎么答

谷歌L5的系统设计面试通常是45-60分钟,但实际有效时间约50分钟。不是时间不够,而是你需要在前5分钟建立信任,否则后面的深度会被质疑。

第一轮:系统设计(45-60分钟)

考察重点不是CRDT的正确性,而是"需求澄清→约束识别→方案论证→权衡显式化"的完整链条。一个常见的开场是:"设计Notion的实时协作功能"。错误的开场是直接进入数据模型:"我会用Yjs的CRDT实现,每个block是一个CRDT document"。正确的开场是:"我先确认几个场景:是支持实时协作编辑,还是也包括评论、权限变更这类非文本操作的同步?

用户规模的上限预期是多少?离线编辑是必须支持的吗?"这三个问题在10秒内抛出,面试官会标记为"strong scoping"。

时间分配建议:前5分钟需求澄清,10分钟高层架构(不是画框图,而是论证为什么选client-server还是peer-to-peer),20分钟核心机制(这里是CRDT的展开),10分钟扩展性讨论,最后5分钟总结和Q&A。不是机械遵守这个时间,而是如果你在前15分钟还没有进入CRDT的具体设计,后面会来不及展示深度。

第二轮:编码/算法(45分钟)

L5的编码轮通常不会直接考CRDT实现,但可能出现"实现一个简化版的协同编辑冲突解决"或"设计一个支持并发的数据结构"。关键区别:L4可能考你实现一个LRU cache,L5考的是"设计一个支持并发写入的key-value store,最终一致"。后者需要你显式处理冲突,但不需要完整的CRDT数学框架。

一个通过的信号:你在写代码前先写注释说明"我假设冲突通过last-write-wins解决,实际产品场景中这里会用向量时钟"。这展示了你知道真实方案是什么,同时在面试约束下做简化。

第三轮:行为/领导力(45分钟)

这一轮常被技术背景的候选人低估。不是让你讲故事,而是让你展示"在模糊情境中推动决策"的能力。一个与CRDT相关的高分故事:你曾在一个项目中需要选择实时协作方案,团队内部对OT和CRDT有分歧,你如何收集信息、定义评估标准、推动决策。关键不是结果选了什么,而是"你如何定义好的标准"——比如你是否把"我们团队的 expertise"放进了考量,而不只是技术优劣。

第四轮:跨职能/产品思维(30-45分钟,部分岗位有)

这一轮会直接挑战你:"如果PM要求支持100人同时编辑一个页面,但技术评估显示CRDT在50人以上性能 degrade,你怎么处理?"不是要你拒绝需求,而是展示你如何与PM共建约束:提出分阶段发布、功能降级方案、或者A/B测试计划。

一个让面试官点头的回答结构:"我会先和PM确认这100人场景的真实发生频率——如果是年会公告这种低频场景,我们可以接受延迟;如果是日常协作,我们需要么限制并发数,要么投入优化。"


> 📖 延伸阅读Notion vs Asana: A Comparison of PM Tools

Notion CRDT vs 谷歌内部方案:比较的真正价值

谷歌内部不是没有实时协作产品,Google Docs的OT实现是经过十年打磨的工业级系统。但在L5面试中比较Notion和Google Docs,不是要比出高下,而是要展示你能"剥离品牌,看到决策约束"。

Google Docs的OT选择根植于其诞生年代(2006年)和场景假设:始终在线、以桌面端为主、Google控制服务器。Notion的CRDT选择根植于2019年的移动优先、离线优先、创业公司资源约束。不是OT过时了,而是两个产品的约束集合不同。

一个危险的面试陷阱是贬低OT来抬高CRDT——这会被标记为"lack of nuance"。正确的姿态是:"在Google Docs的约束下,OT是当时最优解;在Notion的约束下,CRDT的某些特性更匹配——但如果Notion的服务器资源无限且离线不是刚需,OT仍然是一个合理候选。"

更深层的比较维度是"组织能力与架构的匹配"。Yjs是一个开源库,Notion可以基于它快速迭代;Google Docs的OT是深度定制的内部系统,需要专门的团队维护。不是开源vs自研的问题,而是"这个决策在Notion当时的阶段是否合理"。L5的候选人需要展示这种"组织情境敏感度"——同样的技术选择,在A公司是杠杆,在B公司是负债。

一个具体的insider场景:某候选人在面试中提到,Notion后来部分重构了Yjs的序列化格式以优化大文档加载。面试官追问:"如果你来决策,会在什么时候做这种重构?"候选人回答:"在用户投诉加载时间之前,我会在CRDT选型时就评估序列化格式的扩展性。

"这个回答的问题在于"事后诸葛亮"——正确的判断是:早期产品选择标准库快速上线,后期随着规模暴露瓶颈再针对性优化,这是工程资源的理性配置,不是设计失误。展示你能理解"为什么当时不这么做",比展示"我来做会更好"更重要。


准备清单

  1. 亲手实现一个最小化的CRDT文本编辑器,不是用Yjs,而是用原生JavaScript理解state-based CRDT的核心机制——向量时钟、合并函数、因果稳定性。目标不是产品化,而是让你在面试中能画出状态转换图。
  1. 阅读Yjs和Automerge的官方文档各一遍,对比它们的冲突解决策略差异。准备一句话总结:Yjs选择了什么trade-off,Automerge选择了什么。系统性拆解面试结构(PM面试手册里有完整的实时协作系统设计实战复盘可以参考),但不要只依赖二手总结。
  1. 找到Notion、Figma、Google Docs三家产品的实时协作行为差异ogn差异:同时编辑时的光标显示、冲突时的UI反馈、离线再同步时的用户体验。记录三个具体观察,面试中作为"产品敏感度"的证据。
  1. 针对"1000人同时编辑"这个极端场景,准备两个版本的回答:一个是"理想资源下的架构",一个是"资源约束下的MVP"。练习在30秒内切换两个版本,展示你的弹性思维。
  1. 模拟一次与PM的冲突对话:PM坚持要"完全实时的光标同步",你从技术角度解释为什么这会导致服务器成本不可接受。录下自己的回答,检查是否有术语堆砌,确保一个非技术背景的PM能听懂你的核心论点。
  1. 复盘你过去项目中的任何"最终一致性"经验,哪怕是缓存刷新策略。准备一个STAR格式的故事,重点在"你如何向团队解释为什么不追求强一致性"。
  1. 研究谷歌L5的薪资结构:Base $160K-$220K,RSU $120K-$300K/年(4年vest),Bonus 15%-20% of base。不是为谈判,而是为了在行为面试中展示你对职业阶段的清晰认知——"我知道这个级别的期望是什么"。

常见错误

错误一:把CRDT当作分布式系统的"标准答案"来背诵

BAD版本:"CRDT是最终一致的,所以适合实时协作。它的优势是无冲突解决的需要,因为所有操作都是可交换的。"

GOOD版本:"CRDT的最终一致性是有代价的——状态会膨胀,合并计算量随参与节点增加。在Notion的场景里,这个代价被块级结构控制了,因为冲突域被隔离到了block级别。如果是一个纯线性的文本编辑器,字符级CRDT的状态增长会让移动端不可用。"

差异不是信息量,而是前者在"推广CRDT",后者在"限定CRDT的适用边界"。L5的面试官在听你的限定条件,不是在听你的热情。

错误二:在性能数据上做虚假精确

BAD版本:"根据我的了解,Yjs的延迟在5ms以内,内存占用2.3MB,可以支持500人同时编辑。"

GOOD版本:"公开资料中Yjs提到过大文档的内存基准,但实际数字会随编辑历史和block嵌套深度变化。如果面试中需要具体数字,我会先说明我的假设条件——比如这里假设平均每个block 100字符,历史保留30天。"

差异在于后者展示了"数字是工具,不是论据"的认知。面试官可能会故意用一个你没有的数据挑战你,测试你在信息不完整时的推理能力。

错误三:忽视面试官的"转向信号"

BAD版本:面试官说"如果我们不考虑离线场景呢?"候选人继续讲CRDT的离线优势,没有调整。

GOOD版本:面试官说"如果我们不考虑离线场景呢?"候选人立即响应:"那就不需要用CRDT的完整机制了。在始终在线的假设下,OT配合中心化服务器可能更简单,因为冲突可以在服务器单点解决,不需要客户端承担合并计算。但我会保留CRDT的本地缓存作为容错机制,因为'始终在线'是可能失效的假设。"

这个转向展示了"条件化思维"——你的方案绑定于假设,假设变化时方案随之调整。这是L5的核心能力标志。


FAQ

Q: 我没有实时协作产品的经验,怎么在L5面试中显得可信?

不是要你伪造经验,而是要你展示"可迁移的推理模式"。一个具体案例:某候选人来自广告系统背景,没有接触过CRDT,但在面试中将"广告竞价中的并发出价"与"协同编辑中的并发写操作"做了结构映射——两者都需要处理同时发生的、可能冲突的操作,都需要在一致性和性能之间权衡。他没有强行套用CRDT术语,而是说:"在我之前的工作中,我们处理的是竞价版本的冲突,用的是乐观锁+冲突回滚;

我理解CRDT走的是另一条路,接受冲突存在并通过数据结构保证最终收敛,但核心问题域是相似的——如何在不可变约束下最大化并发。"这个回答的价值不在于准确性,而在于展示了"我能把未知问题映射到已知框架"的学习能力。谷歌L5的bar不是"做过什么",而是"面对没做过的问题时,你的推理质量如何"。

Q: 面试官明显比我更懂CRDT,我该怎么处理?

不是回避,而是主动利用。一个真实的HC讨论案例:候选人在面试中直接说:"我对CRDT的实践经验有限,我的理解主要来自Yjs的文档和个人项目。如果我的理解有偏差,请直接纠正我——这对我也是学习机会。"然后在后续讨论中,当面试官纠正他对YATA算法的描述时,他立即调整了后续的推理链条。

HC的反馈是:"Demonstrates intellectual honesty and adaptability — strong L5 signal." 相反,试图掩盖知识缺口、在细节上坚持错误观点的候选人,即使技术深度相当,也会被标记为"rigid"。关键判断是:L5不是知识竞赛,是协作解决问题的模拟;展示你能与更懂的人有效协作,比展示你什么都懂更有价值。

Q: 如果面试官来自Google Docs团队,对OT有偏好,我提CRDT会不会吃亏?

不是会不会吃亏的问题,而是"你如何处理观点冲突"本身就是考察点。一个拿到strong hire的实际做法:候选人在面试中主动提到:"我了解到Google Docs用的是OT方案,我想先确认一下——在这个面试中,我们是假设从零开始设计,还是考虑与现有Google基础设施的集成?"这个问题展示了"情境敏感度"——你不是在真空里做设计。

面试官回答"从零开始"后,他仍然选择了CRDT,但他的论证中包含了"如果是在Google的现有架构下,OT的某些优势会更突出,比如服务器端的成熟优化"。这种"即使我的选择与面试官的偏好不同,我能理解并尊重其合理性"的姿态,被HM在反馈中 explicit 提及。不是要你讨好面试官,而是展示你能把"不同意见"作为信息输入,而不是威胁。


准备好系统化备战PM面试了吗?

获取完整面试准备系统 →

也可在 Gumroad 获取完整手册

相关阅读