我错了。未来是CRDT

几周前,我观看了马丁·克莱普曼(Martin Kleppman)关于他通过CRDT进行实时编辑的方法的演讲并感到绝望。他的方法是如此出色,以至于在过去十年中超越了我的所有工作,并且将来将无处可去。



但是,让我们重新开始。



2010年,我在Google Wave工作,我们试图创建协作式可编辑空间来替代电子邮件,Google Docks,论坛,即时消息传递和许多其他单任务应用程序。在我的工具中,我特别喜欢通用环境,而在Wave中其他地方,当时还没有制定功能。与大多数其他工具不同,通用环境不会强加自己的工作流程,因此您可以使用它来计划假期,创建Wiki,与朋友一起玩棋盘游戏,安排工作会议等等。



在内部,Wave联合编辑基于操作转换(OT)进行工作,并且在那时已经存在了几天:我们的算法基于1995年的Jupiter演讲。对于每个文档,该算法保留一个单独的按时间顺序排列的更改列表,即“位置0处的Type H”,“位置1处的Type i”,依此类推。在大多数情况下,用户更改文档的最新版本,日志看起来像是一系列更改,但是,在共同创作时,我们面临着同时进行的编辑。



在这种情况下,照常记录到服务器的第一个编辑,然后将下一个(如果发现已过时)与事件日志进行比较,以确定用户的初始目标。 (通常,所有这些都取决于更新字符位置。)然后,该算法(据说是“用户想要的结果”)实时添加了一个新操作,例如git-rebase。



随着Google Wave的关闭,我将OT模型移植到了ShareJS。那时,节点感觉很新而且很奇怪,如果我没记错的话,我甚至在npm发行之前就启动了ShareJS。一个简单的共同编辑者只需要一千行代码,在演示中,我在浏览器和应用程序中共同编辑了该文档。



OT的核心是修饰()的循环具有多个帮助功能,用于更新字符偏移量。实际上,OT很简单,易于理解,可以快速投入运行并且效果很好。(未优化的javascript每秒10到10万次操作,优化的C每秒1到2000万次操作)。事件日志可能比平时消耗更多的内存,但是您可以将其缩减,尽管您将无法合并特别是旧的编辑。全局分配操作将需要一台集中式服务器,但是大多数系统已经具有这样的服务器或数据库,不是吗?



集中式服务器



OT的一个重要问题是它对中央服务器的依赖性。您是否曾经想过,为什么在允许通过社交网络访问Google Docs文档时,会遇到一条奇怪的消息,例如“此文档超载且其编辑被禁用”?原因(在我看来)如下:当您打开一个文档时,选择了一个特定的服务器来处理其所有编辑,并且当大量用户跳动该文档时,系统必须非常努力地避免服务器超负荷。



有多种方法可以解决此问题:除了子文档分片(如Google Docks)外,您还可以通过重试循环绕过数据库事务进行编辑,从而使序列化问题落在同一数据库的肩上(这就是Firepad的工作方式)ShareDB)。



但是,旧约并不完美。我们想用Wave代替电子邮件,但是邮件支持合并,一连串的信件可以跨越许多公司,并且某种程度上一切都能成功进行。另外,与Facebook消息不同,电子邮件可以发送给“副本”列中提到的公司。如果我们希望Wave替换邮件,它还需要在不访问外部网络的情况下发送消息的功能,例如,当我向下表中的同事发送信件时。但是如何在OT之上实现所有这些功能呢?我们设法以某种方式建立了这样一个过程,但结果却太复杂且充满错误:我们创建了一个图表,其中每个wave协议都建立一棵wave服务器树来双向传输操作,但从未完全起作用。不到十年前,在Wave协议峰会上,我做了一个关于如何创建和配置这样的网络的演讲,但是尽管我做了所有准备和所有初步检查,但严格遵守演讲本身的每个步骤还是失败了,并且该网络从未奏效。我仍然不知道为什么会这样,但是无论有什么错误,它们都很难在公共版本中修复,这太困难了。



起飞CRTD



正如我已经提到的那样,Wave的主要算法是在很久以前(即1995年)创建的,当时我甚至都不记得当时在家中拥有Internet。自那时以来,研究人员一直在不懈地努力以提高OT的性能,并在最有希望的方向上使用CRTD(无冲突复制数据类型)。这种方法与通常的方法有所不同,它允许您实时编辑文件,而无需中央服务器。Martin的演示文稿比我能描述的更好地描述了他们的工作,因此我将跳过这些细节。



多年来,人们一直在问我对CRTD的看法,我的回答听起来总是这样:



它们很整洁,我很高兴人们正在为它们工作,但是:


  • . . , 100 Delta-CRTD . (: B4.)
  • - CRTD , , 100 automerge master 83 . , , , , . ( automerge 1.1 .)
  • 多年以来,OT中存在的功能在CRDT中是不存在的,例如,还没有人制作过支持/ object move /(将某些内容从JSON树的一部分转移到另一部分)的CRDT。这样的程序是诸如Workflowy之类的应用程序所必需的,而OT可以很好地完成这些工作
  • CRDT本身很复杂,很难推理。
  • 您很可能已经拥有一个集中式服务器/数据库。


对于我的所有批评,我都忽略了CRDT,但是这样做却忽略了相关文献,令我惊讶的是,我错过了CRDT的默默无闻的改进。在他的演讲中(值得您关注的多),马丁阐述了要点:



  • : CRDT (Automerge / RGA Y.js / YATA) [log(n)] . ( .)
  • : - , 54- . automerge , Y.js, Y.js 100 160 3 . .
  • : , .
  • : , CRDT OT. , automerge .


速度的原因并不能使我信服,因此为了测试该想法,我使用来自自动合并的想法通过B树在Rust中独立实现和测试了CRDT。它没有功能(删除字符,冲突),但是每秒能够处理600万次编辑。 (每个迭代由两个交替的用户对空白文档进行2000次编辑,总共花费330微秒,即每秒进行606万次编辑。)因此,CRDT确实得到了改善,它们与OT之间的速度差现在甚至小于Rust与Javascript。



所有这些修补程序已经在automerge性能分支的“即将推出”部分中存在很长时间了,但是毕竟automerge并不是唯一的CRDT。Y.js证明了自己的价值,并在其测试中轻松绕过了当前版本的automerge。它缺少我感兴趣的功能,但是总的来说,修复现有的实现肯定比创建新的算法容易。



创造未来



我非常担心取得进展。一百年不使用会有什么奇怪的?显然,我们将进行实时编辑,但是我不再确定它是通过旧版实现的,以及我在这方面所做的所有工作,这让我感到不安。



如今,JSON和REST无处不在。假设从现在开始的15年后,实时协同编辑也将无处不在。在共同创作方面,JSON相当于什么,以便轻松转移到您的项目?在这个光辉的未来,我们将需要高质量的CRDT实现,因为对于某些应用程序OT根本无法使用,无法通过它或简单的Google Wave变体来创建GIt的实时版本。但是,如果我们已经有良好的CRDT实现,是否还需要OT实现?我认为不是,因为将所有功能从OT转移到CRDT并不困难(顺便说一下,包括剪切操作),而事实并非如此。聪明的人不同意我的看法,但我认为,鉴于我们对每种语言都有很好的快速CRDT,OT的需求将完全消失。



OT的优点之一是,它可以像大多数现代应用程序一样在集中式系统中轻松实现,但是分布式算法也可以很好地实现。(例如,看一下Github。)在我看来,在wasm上进行高质量的CRDT比在JS中实现OT更快。而且,如果您只关心集中式系统,请记住:OT限制导致Google扩展了Google文档中的问题。



因此在我看来,现在是时候切换到快速的小型CRDT了。大部分情况下,学术工作已经完成,成功实施的问题仍然存在。



下一步是什么



我越来越不关心集中式应用程序的领域。应用程序在我的设备上与我的数据进行交互,这些应用程序需要相应时间对这些连接做出反应。我希望我的笔记本电脑和手机能够通过wifi相互传输数据,而不是通过将数据上传到其他国家/地区的服务器来实现。尤其是如果这些服务器是由广告巨头竞相吸引我的注意力的



从哲学上讲,当我在Google文档中编辑文档时,我的计算机向Google授予编辑该文件的权限(因为服务器出于某种原因拒绝了,我会丢失所有编辑内容)。为了进行比较,当git push在github中时,我只是通知有关我代码中的编辑的github。我的存储库仍然属于我,它包含的所有数据和硬件也属于我,这就是我的应用程序应该如何工作的。多亏了像Martin这样的人,我们现在知道如何制作优质的CRDT。但是,在接受本地优先应用程序作为基础之前,必须编写更多的代码行。



总之,是时候告别运营转型了。在我写的所有文章中,我们在一起度过了愉快的时光,操作转换代码 是最困难和最有趣的代码之一。您是一个聪明而令人惊叹的OT,但是CRDT可以做您永远无法做的事情。我需要CRDT。我认为,通过一些好的实现,我们可以实现一些非常特别的东西。



多年来,我为我在OT上所做的所有工作表示哀悼,但OT不再适合我对未来的愿景。CRDT将使我们能够更轻松,更快速地重建Wave,并创建将用户视为数字公民而不是数字农民的应用。这很重要。



是时候创建了。



All Articles