如何设计 Google Docs
译者:飞龙
自豪地采用谷歌翻译
系统设计面试可能相当开放,需要广泛的知识。
为了准备好这样的面试,重要的是要覆盖不同的领域,而不是集中在单一的主题。我们花了很多时间选择系统设计问题进行分析,我们的主要标准是:
- 这个问题是流行的和经典的
- 我们关心我们选择的问题的多样性
- 分析有助于其他面试问题
本周,我们想讨论如何设计 Google 文档。你会发现它与我们以前的问题的分析有很大的不同。
问题 - 如何设计 Google 文档
我会假设每个人都知道Google文档是什么,不会浪费时间介绍这个产品。
乍一看,这个问题看起来相当普遍,事实确实如此。 Google 文档是一个庞大的系统,具有很多功能。如果你花几分钟时间思考这个问题,则可能会意识到 Google 文档比看起来复杂得多。
作为一个面试官,我不想把讨论的范围限制在这个产品的特定功能上。相反,我倾向于把这个问题提出来,使我能够知道候选人将如何逐步解决一个模糊的问题。
划分为组件
在我们以前的帖子中,我们已经多次强调,当问题很大时,建议提供概要解决方案。抽象解决方案的一种方法是,将大系统分成更小的组件。
显然,Google Docs 是一个庞大的系统,具有一系列功能,包括文档存储,共享,格式化,编辑等。事实上,如果不把它分解成不同的子问题,我几乎不能解决这么大的问题。
如果你没有考虑过这个问题,请在查看我们的分析之前,花费 5-10 分钟的时间自行解答。另外,值得注意的是,如果你的解决方案与我们的解决方案不同,那么问题就是开放的,这是绝对没问题的。
我们可以把整个系统分成以下几个主要部分:
- 文件存储。由于 Google 文档是 Google 云端硬盘的一部分,因此我也包含了存储功能。该系统允许用户将文件(文档)分组到文件夹,并支持编辑/创建/删除等功能。它像一个操作系统。
- 在线编辑和格式化。毫无疑问,Google 文档的核心功能之一就是在线编辑。它支持几乎所有的微软 Office 操作,也许更多。
- 合作。 Google Docs 允许多个人同时编辑单个文档,这真是太神奇了。这肯定是一个技术挑战。
- 访问控制。你可以与你的朋友分享文档,并给予不同的权限(所有者,只读,允许评论等)。
这里忽略了一些不太重要的功能,像插件,拼写检查,发布到网络等等。
存储和格式化
我将这两个话题放在一起,因为在实现存储和格式化的过程中,会创建一个 Google Docs 非常基本的初级的版本。即使没有访问控制和协作,单个用户仍然可以使用它来编辑文档。
另外,存储和格式化在一定程度上可以看作是后端和前端。
恕我直言,Google Docs(或 Google Drive)的存储系统非常接近操作系统。它有像文件夹,文件,所有者等概念。
因此,构建这样的系统,基本积木是一个文件对象,它包含内容,父项,所有者以及其他元数据,如创建日期。父项代表文件夹关系,根目录的父项为空。我不会讨论如何扩展系统,因为构建分布式系统可能非常复杂。有很多事情要考虑,比如一致性和复制。
对于前端的格式化,一个有趣的问题是,如何使用相应格式储存文档。如果你了解 Markdown,那绝对是最好的解决方案之一。尽管 Google Docs 可能更复杂,但 Markdown 的基本思想仍然适用。
并发
Google Docs 最酷的功能之一是可以同时编辑多个文档。你将如何设计这个功能?
说实话,这不是一个容易的问题。你不能只让每个人自己工作,然后合并每个人的副本或选取最后一次编辑。如果你已经尝试了协作编辑功能,你实际上可以看到对方正在做什么,并获得即时反馈。
如果你已经使用 Git 进行版本控制(译者注:或者简单的diff
和patch
),这里的一些想法可以是类似的。首先,让我们考虑最简单的情况 - 只有两个人在编辑同一个文档。假设文档是abc
。
基本上,服务器可以为每个人保留量份相同的文档,并跟踪完整的修订历史。当 A 通过在开头添加x
来编辑文档时,这个改变将与 A 所看到的最后修订一起发送到服务器。假设此时 B 删除最后一个字符c
,并且这个改变也是这样发送到服务器。
由于服务器知道修改在哪个版本上进行,因此会相应地调整更改。更具体地说,B 的变化是删除第三个字符c
,它将被转换为删除第四个字符,因为 A 在开头添加了x
。
这就是所谓的操作转换(Operational Tranformation)。如果你从没听说也没关系,基本思想是根据修改和其他合作者的修改来转换每个人的改动。
访问控制
Google 文档允许你使用不同级别的权限邀请合作者。
朴素的解决方案不应该很难。对于每个文件,你可以维护一个合作者列表,带有相应权限如只读,所有者等。当一个人想做特定的行动,系统检查他的权限。
通常,我想问一下这种访问控制系统所面临的挑战是什么。
众所周知,将系统扩展到数百万用户时,可能会有很多问题。我想在这里提到的几件事是:
- 速度。当所有者更新文件夹的权限(例如删除特定的查看者)时,应将此更新传播给其所有子项。速度可能是一个问题。
- 一致性。当有多个副本时,保持每个副本的一致性尤其重要,特别是当多个人同时更新权限时。
- 传播。可能有很多传播情况。除了更新文件夹的权限应该反映在所有的子文件之外,如果你向某人授予文档 D 的读取权限,那么他也可能已经拥有了文档 D 的所有父文件夹的读取权限。如果有人删除了 D 文件,我们可能会撤销 D 的父文件夹的阅读权限(也许不是,这更像是产品决策)。
总结
同样,Gainlo 中没有人从事过 Google Docs。 这篇文章没有教你如何从头开始构建 Google Docs。
相反,我想用这篇文章给你更多想法,有关如何进行系统设计面试和如何解决模糊问题。
设计一个像 Google Docs 这样的复杂系统可能会让人感到恐惧。 但是一旦你把系统分成更小的组件,就变得简单多了。
如果你觉得这篇文章有帮助,请分享给你的朋友,我会很感谢。 你也可以在这里查看更多的系统设计面试问题和分析。