耶鲁大学教授从构建生产数据库中学到的 42 件事 - maheshba


2017 年,我在耶鲁大学教职期间休假去了 Facebook。我创建了一个团队,在 Facebook 堆栈的底部构建一个名为 Delos 的存储系统(将其视为 Facebook 版本的 Chubby)。在不到一年的时间里,我们以一个 3 人的团队投入生产;随后将团队扩展到 30 多名工程师,跨越多个子团队。在我领导团队的四年中(直到 2021 年春季),我们没有遇到过一次严重的中断(不超过 SEV3)。Delos 设计在两篇学术论文(OSDI 2020SOSP 2021)中有详细记录。Delos 目前正在取代 Facebook 对 ZooKeeper 的所有使用。
以下是我作为 Delos 的技术负责人学到的一些东西。我发布这篇文章的目的是帮助其他类似角色的人(在大公司构建新基础设施的领导团队);其中大部分可能无法推广到不同的设置。
 
客户

  • [1] 让您的客户满意;否则本文档的其余部分无关紧要。
  • [2] 小心拥有正确数量的客户(一开始,只有一个)和正确的客户(他们的需求允许您构建关键技术);并小心地增加这个数字。
  • [3] 直接与客户 IC 接口。很多团队内部的冲突可以通过说“我刚刚和客户谈过,他们说……”来解决。在基础架构中,我们通常不需要推测客户想要什么;我们可以问问他们。
  • [4] 但要意识到客户可能不会表达他们真正需要的东西;不要从表面上看需求,而是花时间详细了解他们的用例。阅读他们的代码。

 
项目管理:
  • [5] 有一个简单明了的使命宣言来表达你的存在理由。对于 Delos 而言,它是:我们将成为 FB infra 的可靠基础。
  • [6] 重复社会化任务难度的估计;决策者可能没有时间、倾向、背景或培训来生成这些估计值,并且可能会错误地(字面意思)出现数量级的错误。
  • [7] 任务分配给 IC 很关键;要求处于任何决策的关键路径中,因为您通常比经理更了解问题、代码库和 IC 的优势。如果您和其他 IC 自行确定任务分配,大多数经理都会感到兴奋。
  • [8] 路线图是一种手段,而不是目的。
  • [9] 如果你得到了优秀的和/或一致的经理,尽可能地理解、支持和包容。如果你没有这样的经理......好吧,我还没有弄清楚这一点,如果你做到了,请告诉我。
  • [10] 使您的项目健壮以适应重组。公司的管理层级本质上是脆弱的(树毕竟是一个 1-连通图);与未来可能接手的经理不断地交流项目。尽一切努力确保经理流失不会给 IC 带来不公平的职业结果。
  • [11] 跟踪类似功能在您所在领域的其他项目中花费的时间,并将其用作估计任务难度的证据(例如,“功能 X 在系统 Y 中花费了三年时间;这不是一个 IC 的一半工作。 ”)。

 
设计:
  • [12] 对 API 持保守态度,对实现持开放态度。
  • [13] 但坚持围绕推出新实现(影子、分阶段推出)的谨慎过程。
  • [14] 在设计 API 时,为一种实现编写代码;积极筹划二次实施;并希望/祈祷事情将适用于第三次实施。
  • [15] 设计 API 时将迁移到新的实现作为首要考虑;自定义迁移是巨大的时间消耗和不可靠性的来源。每个主要 API 都应该有一个单一的 CLI 驱动调用来切换实现。
  • [16] 团队设计;作为个人实施。这将使设计成为瓶颈,但这是值得的:推迟并行化设计的冲动。
  • [17] 对于存储系统,一开始就严重偏向于一致性和持久性,而不是可用性;这些更难测量,如果损坏则更难修复。因为可用性更容易衡量,所以会有外部压力优先考虑它;推回。
  • [18] 在 API 测试中维护多个实现;比较它们之间的结果。成本是值得的(这将有助于提高正确性,并防止泄漏实现细节)。
  • [19] 设计后期绑定:鼓励团队考虑整个设计空间,而无需致力于特定的点解决方案。与一群高智商、固执己见的 IC 进行头脑风暴会议是一门值得掌握的艺术。鼓励在绑定到设计的关键路径中进行粗略的原型设计。
  • [20] 对实现者的后期绑定:一旦设计完成,任何 IC 都应该能够编写代码。
  • [21] 有正确数量的抽象(这很难)。太少了,你最终会得到一个凌乱的巨石;太多了,团队将被理解每个抽象语义的认知开销所淹没。
  • [22] 避免使用实时来保证正确性或跨机器比较时钟,除非您有(并理解)时钟上的误差界限。
  • [23] 拥有单一的事实来源。在各种类型的状态之间建立简单的不变量。
  • [24] 营造一种文化,让 IC 不断思考完全不同的设计;不要关闭有关假设性替代设计的对话。鼓励好奇心。
  • [25] 了解您的 SKU。云基础设施很容易忽略硬件;但是对硬件(和硬件趋势)的理解对于设计至关重要。

 
代码审查:
  • [26] 在具有快速审查周期的透明代码库中,API 将泄漏实现细节,除非您保持警惕。
  • [27] 鼓励 IC 对差异进行批判性思考,并创造一个人们可以自由表达疑虑的环境。作为差异作者,您对指出差异问题的人的回应应该是感激,而不是沮丧。
  • [28] 对于关键组件,请考虑非正式规则,例如要求来自某些 IC 子集的两个接受或什至一致接受。
  • [29] 对于关键组件,登陆差异的时间不是一个重要的指标:抵制冲动来衡量这个指标并优化它。创造一种文化,在这种文化中,IC 没有问题,差异不会很快落地(创造性的努力——书籍、论文等——由于高质量审查的成本,通常需要很长的审查周期;为什么代码应该不同?)。
  • [30] 有时,只有在 IC 将候选设计编写为差异之后,您才会意识到某些东西的正确设计。克制说“哦,好吧,让我们降落然后再修复它”的冲动;你这样做并没有帮助 IC 或项目。创造一种文化,如果代码不是正确的解决方案(以身作则),IC 可以轻松地丢弃代码。

 
战略:
  • [31] 以某种节奏问问自己:团队/项目为什么存在?如果它不存在,会发生什么(哪个团队/系统会填补空白)?团队如何为公司增加价值,未来如何继续这样做?
  • [32] 跟踪公司内您所在领域的所有其他重大项目:您应该能够比他们自己的 IC 更好地解释他们的技术设计。抓住任何机会与其他类似项目的负责人讨论范围:您应该能够阐明您的项目如何适应更大的选项生态系统。团队间的竞争是健康的,也是必要的。在这些项目中与 IC 成为朋友:他们比公司中的任何其他人都更了解您的技术挑战。
  • [33] 不要在原始表现或效率上与其他团队竞争;这将升级为军备竞赛,双方团队都浪费时间针对点工作负载优化他们的系统,生成苹果与橙子的比较等。在基本设计特征上展开竞争。
  • [34] 如果有人客观上为您的用例提供了更好的系统并希望采用它,那就去寻找其他事情做。

 
可观察性:
  • [35] 测量是一种手段,而不是目的。
  • [36] 您应该能够在您的客户之前发现您的服务中的问题。
  • [37] 尽可能地,可观察性应该在 API 之上并在实现之外。这确保您可以切换实现并比较性能,而不会在测量代码中引入错误。它还使实现变得整洁;并降低了新实现的门槛。
  • [38] 任何不能轻易衡量的东西(例如,一致性)常常被遗忘;特别注意难以衡量的属性。
  • [39] 尽可能将关键检查(例如一致性)推入部署本身​​;尽量减少对外部检查服务的依赖(否则您现在需要跟踪两件事而不是一件)。

 
研究:
  • [40] 跟踪您所在领域的研究。很快,您的 IC 就会有一个速记,可以实现超快速通信:“如果我们从 projectX 尝试那个东西怎么办?并将其与 projectY 中的技术结合起来?”。
  • [41] 尝试新事物。在可行解决方案的空间内偏向新颖性。打击逐字复制设计的冲动。每个主要系统在某个时候都只是某人头脑中的一个不成熟的想法。
  • [42] 写论文。为一个对你所做的事情没有任何背景的观众写作将迫使你检查和澄清你的假设。论文使雇用优秀人才和加入他们变得更容易。研究生应该能够向你解释你的设计(并找到错误!)。当被要求发表演讲时,试着说是。他们很有趣,你可以结识新朋友。