编者按: 《架构真经》 一书在 《前车之鉴》章节 以实际教训总结了看似简单的几条规则,分别是 失败乃成功之母 、不靠QA发现错误、不能回滚注定失败。 其中“”可回滚“”的规则曾经让PayPal公司印象深刻,因为不提供回滚让他们日子过得不错-这种做法在版本24.0之前从来没有给业务带来任何重大的问题。然后暗黑时刻不期而至......
▲重视失败能够让一个公司快速成长
长期研究的结果表明:从失败而不是成功中能学习到更多的东西。 但是,只有营造开放和诚实沟通的环境,同时辅以能帮助我们反复从错误和失败中吸取教训的轻量级过程,才能真正地从失败中吸取教训。 若隐藏失败,结果必然是反复失败,不如努力营造把分享失败作为最佳实践反模式的环境。要想成功,我们需要观察客户并把每次失败当成一个吸取教训的机会来积极学习,适当地依靠像 QA 这样的组织,预期系统失败,并针对这些失败做好充分的准备。下面的故事说明了一家公司如何能够深入和广泛地学习。
▲ Intuit的成长——错误一直会出现,需要一直改变
Intuit是美国的一家软件公司,它为小型企业、会计师和个人提供财务与税务筹划软件及其相关服务。截至 2015 年, Intuit 是一家市值接近 260 亿美元的非常成功的全球化公司,营收 41.9 亿美元,员工超过 8500 人。 Intuit 由斯考特·库克和汤姆·普鲁于 1983 年创建,他们的第一款产品完全基于台式机和笔记本电脑。到了 21 世纪初,消费者行为开始改变——用户开始期待曾经在自己系统上运行的产品可以作为服务在线交付(软件作为服务),甚至最终通过移动设备使用。 Intuit 很早就看到了这个趋势,多年来,包括 Quicken 、 TurboTax 和 QuickBooks 在内的许多款产品都在研发网络版和移动版。通过向 SaaS 和移动两个方向过渡, Intuit 迅速学习,但他们每次都采取非常不同的方法。下面的故事是 Intuit 在向 SaaS 和移动过渡的旅程中学习的例证。
在Intuit的业务向 SaaS 过渡的过程中,其托管 SaaS 产品的知识受到了局限。由首席技术官泰洛·斯坦布里领导的信息技术部是一个不断成长的团队,他们负责基础设施,软件解决方案就运行在这些基础设施之上。“在 2010 年,我们有一个相当重要的数据中心,发生了由配电单元[ PDU ]失效所引起的故障。”斯坦布里说。“修理工进来修理 PDU ,在修理第一套设备时,不小心使同类型的其他 PDU 也瘫痪了。数据中心彻底停电,有个存储单元因停机不当,结果造成数据完全损失。花了近 24 小时才恢复数据,让所有应用恢复运行。”
幸运的是,这个事件不是发生在Intuit的高峰期,错开了工资和税收季节。( Intuit 收入中的相当大一部分来自于多个产品线的季节性高峰期,诸如美国的报税季节。)泰洛说道,“受损客户量不小,但情况可能会更糟糕。”假如故障发生在产品线的旺季,会对公司造成更大的损失,所以这次事故可以作为对团队的一个很好的提醒。在某种意义上它是完美的警告,使每个人都知道我们在这方面知识匮乏。他们动作机敏,每个团队都立即召开了深度讨论会,检讨如何能把主动/被动架构转变成主动 / 主动架构。然而,当泰洛开始查看 Intuit 如何能理解并尽早解决这些问题时,结果发现很多推动这些努力的人,并没有适当的 SaaS 架构经验,而且也不知道该怎么提出合适的问题。
例如,有个应用负责人询问团队是否具备故障转移能力。有人告诉她团队具备故障转移能力,但是没有给出更多细节,结果她并没有意识到,所谓的故障转移能力只针对少数几台QA服务器。好消息是这些服务器位于另一个数据中心。坏消息是这些服务器只能用于测试,无法扩展以满足生产流量,而且从来都没有运行过全套软件和服务。这位负责人相信,基于她问题的答案,系统已经得到了保护。泰洛说,“她没有追问第二、第三和第四级问题,以确保团队进行故障转移演练。”意识到团队负责人缺少大型 SaaS 系统扩展方面的知识,他开始亡羊补牢。
在接下来的两年里,泰洛招募技术团队的总监和副总裁,要求他们具有架构和研发高可用SaaS系统的知识与经验。这并不是把每个人都换掉,但泰洛保证引入了足够多的新才俊,足以对墨守成规、根深蒂固的团队加以改变。多才多艺的新人也带来了大量新知识与新文化。该方法在很短的时间内生效,团队开始在新的主动 / 主动高可用架构下勤奋工作。
Intuit团队在向移动转型的过程中也开始意识到他们没有合适的技能。因为 Intuit 公司在桌面空间里长大,毫不奇怪,公司有很多桌面工程师。但是没有移动应用的研发者。泰洛继续说道,“硅谷的每个公司都在构建移动应用,移动设备不再只是供你玩游戏,真的可以在上面做重要的金融交易处理和构建金融系统,一旦整个公司的重心都倾斜到这个想法上,对我们而言,移动就成了件轻而易举的事。”泰洛解决该问题的方法是把桌面工程师改造成移动研发工程师。
泰洛说,“事实证明,桌面和移动架构确实具有相当大的同构性。我们可以改造桌面工程师,经过一个月的 Android 或 iOS 培训后,马上让他们在构建高质量的移动应用的过程中发挥作用。在网上你可以一天发布几次应用。但每次发布到客户端前都必须要先打好包,当用户在使用应用时,你无法频繁地更新它。我们刚好有一群工程师有相关环境的构建经验。你失去了一点点屏幕空间,但得到的是一些在桌面系统上所没有的传感器,此消彼长。”泰洛的观点是,有时缺乏的知识必须从外部获得,有时可以培训现有员工。这些决定要求技术领导者运用自己的专业知识做出判断。
Intuit 的故事告诉我们, 组织必须在深度和广度上学习。 学习的深度来自于多问 “为什么”,直到原因清楚、答案确定。学习的广度不仅来自于为做出更好的产品而查看在技术和架构上需要的修改方案,还来源于我们需要什么样的培训、人、组织和流程。像数据中心故障这类事件的损失是巨大的,我们必须从中深入并且广泛地学习,以防止类似的故障再次发生。
规则 27——失败乃成功之母
内容: 抓住每个机会,尤其是失败的机会,学习经验并吸取教训。
场景: 不断地从错误和成功中学习。
用法: 观察客户或用 A/B测试验证。建立事后分析过程,在低故障率环境下采用假设失败的方法。
原因: 做事情不考虑结果或发生事故而没有从中吸取教训,都会错失良机,从而让竞争对手趁机占便宜。最好的经验来自于失败中的错误,而不是成功。
要点: 要不断努力地学习。学习得最好、最快和最频繁的是那些增长最快并且最具可扩展性的公司。千万不要浪费失败的机会。抓紧每个机会学习,发现架构、人和过程中需要纠正的问题。
▲不要轻易觉得自己所掌握的信息足够的多
贵组织中是否有人认为他们掌握了构建大型可扩展性产品所需要知道的一切?或者贵组织是否认为自己比客户知道得更多?是否听到有人说过顾客不知道自己要什么?虽然客户不一定能说清楚,但这并不意味着他们在看到时不知道。不能抓住每个机会持续地努力学习,使你在不断学习的竞争对手面前不堪一击。
对互联网社区传染(也称为病毒式增长)产品和服务的持续研究揭示出,拥有学习文化的组织更易于实现病毒式增长。下面的介绍假定你不熟悉社区传染和病毒式增长的术语,病毒起源于流行病学(研究人群的健康和疾病的科学),互联网社区传染用来解释互联网公司产品如何快速在用户之间传播的现象。用户呈指数型增长称为病毒式增长,指的是人们有意识地相互分享信息。在自然界中,大多数人不是故意传播病毒,但是在互联网上他们以信息或娱乐的形式进行,由此产生的传播与病毒传播相似。一旦这种指数增长开始,就有可能准确预测它的速率,因为它遵循幂律分布,直到产品达到一个平衡点。图7-1显示了某个产品累计用户数的病毒式增长(实线)情况,以及另外一个产品因为 10% 的差距错失了引爆点的情况(虚线)。
▲高频率地交流
创造学习文化的重要性不可低估。即使对实现病毒式增长不感兴趣,如果想要为客户做出好产品,就必须愿意学习。学习有两个方面是至关重要的。首先,如前所述,从客户那里学习。其次,从业务/技术的运营中学习。我们依次对两者进行简短的讨论。这两个方面都仰赖优秀的聆听技巧。相信上帝给了我们两只耳朵和一张嘴是在提醒要多听少说。
焦点小组很有趣,因为他们有机会坐下来聆听客户的想法。问题是,像大多数人一样,客户实在不知道应该如何向我们反映产品的情况,直到在自己客厅或者电脑上看到和感受到为止。不要在哲学领域里深究为什么,但这里部分是由所谓的社区建设造成的。简单地说,通过把社会群体中最广泛的含义赋予事物(确实是一切,有人认为这样做是为了现实本身),我们让一切有意义。虽然我们可以形成自己的观点,但是它们通常只是反思或建立在别人相信什么的基础上。那么,你应该如何解决不相信顾客说法的问题呢?快速发布并观察客户的反应。
可以以好几种方式观察客户。简单地跟踪使用情况和采用新功能是一个好的开始。比较经典的A/B测试甚至更好。把客户随机分为 A 和 B 两组,并允许 A 组访问某个产品的某个版本, B 组访问其他的版本。通过结果比较,如放弃率、现场花费的时间、转换率等,以确定哪个版本执行得更好。很明显,对被测量的指标必须要有前瞻性的考虑,但这是用来比较产品版本优劣的既好又相当准确的方法。
如果想在技术和商业运作上实现可扩展性,就必须不断地了解其他领域。绝不能让事件或问题从眼前溜过而不从中学习。网站的每个问题、事故或停机都是学习如何在未来把事情做得更好的机会。
许多人在社交聚会上讨论世界大事时,都可能会说:“我们似乎从来没有从历史中吸取教训。”但有多少人真的用这个标准来衡量自己、我们的创新成果和所在的公司?在涉及高可用性与高可扩展性技术平台的领域里存在着一个有趣的悖论:构建那些系统的目的就是防止频繁失败,因此可以学习的机会也比较少。这个悖论的固有含义就是每个过程、系统或人员的失败给我们提供了事后分析、学习的机会。不能利用这些宝贵的事件来优化人、流程和架构,注定要继续日复一日、年复一年地持续运作,这也意味着无法改善。如果无法改进,出现在超高速成长业务背景画布上的就是描绘业务失败的画面。当业务增长太快时,在业务中会发生太多的事情,以至于我们无法相信当初设计的 x 倍扩展解决方案将能够支撑 10x 倍业务的扩展。
▲拥有良好的预知问题和应对能力
核能发电领域为需要从错误中学习提供了有趣的见解。1979年,美国三里岛的 TMI-2 反应堆部分堆芯熔化,造成美国历史上最重大的核事故。这次事故为几本书,至少一部电影,以及两个重要的理论提供了素材,这些理论是有关如何在事故罕见但是代价昂贵的环境中学习。
查尔斯·佩罗的正常事故理论,假设现代耦合系统所固有的复杂性使事故不可避免[ 1 ]。这些系统的固有耦合性造成相互作用迅速升级,使人类或控制系统成功交互的机会几乎没有。回想一下你多久看一次监控系统,可以在监控从全部“绿色”变成几乎完全“红色”之前,响应第一个报警消息。
托德·拉波特提出了高可靠性组织理论,他认为即使在没有事故的情况下组织也可以学习,并以组织战略来实现更高的可靠性[ 2 ]。
尽管这些理论存在着不一致性,但是它们有一些共性元素。首先,经常失败的组织往往有更好的学习和成长机会,当然假设他们能够抓住机会并从中学习。其次,在前面理论的基础上,很少失败的系统几乎不提供学习机会,在团队没有其他办法的情况下,系统不会增长和改善。
强调了从错误中学习和改进的重要性,暂时偏离这个主题,简单地描述一个可以学习和改进的轻量级过程。对于我们所经历的任何重大问题,我们相信公司应该采用事后分析的过程,通过截然不同但容易描述的三个阶段来解决这个问题。
■ 阶段 1 :时间轴 ——聚焦在时间轴上描绘引起问题或危机的那些事件。在这个阶段,除了时间轴以外,什么都不要讨论。一旦参加会议的每个人都一致认为再没有更多事件要添加到时间轴上,该阶段就结束了。通常会发现,即使已经通过了时间轴阶段,人们还是会在事后分析的下一个阶段继续想起或发现值得在时间轴上标注的事件。
■ 阶段 2 :发现问题 ——过程的协调者和团队一起回顾时间轴并发现问题。监控先在早上 8 点发现客户失败,但直到中午才有人响应,可以这么做吗?为什么数据库的自动故障转移没有按照预期设计发生?为什么相信删除表会使应用恢复运行?在时间轴上发现了每个问题,但暂时不纠正或采取行动直到团队发现全部问题。团队成员总是提出行动建议,但是过程协调者有责任让团队在第 2 阶段聚焦在发现问题上。
■ 阶段 3 :明确行动 ——每个问题至少应该有一个措施与其相关联。对于列表中的每个问题,过程协调者与团队合作确定措施、拥有者、预期的结果以及完成时间。应用 SMART 原则,每个措施都应该是具体的、可度量的、可实现的、现实的、有时间性的。即使该行动可能需要一个小组或团队来完成,也应该确定单一的拥有者。
在没有解决导致故障的人、过程和架构问题之前,不应当认为事后分析过程是完整的。我们经常发现客户在事后分析中,把“服务器宕机”作为事件的根本原因。与人和过程一样,硬件失败,单一组件故障都不应该被视为任何事件“真正的根本原因”。对任何可扩展性或可用性失败,真正要问的问题是,“为什么系统整体不能表现得更好一些?”如果数据库加载失败,我们可以问,“为什么团队没有更早地发现这个需要?”应该设立哪些过程或监控环节以帮助我们发现问题?为什么从失败中恢复要这么久?为什么不拆分数据库以减轻故障对客户群或服务的影响?为什么不能把只读数据库快速升级为可写数据库?根据我们的经验,除非你能回答至少五个“为什么”来涵盖五种不同的潜在问题,否则不算完成调查。问五个“为什么”很常见,但有点武断,你应该继续盘问直到没有什么新发现。这个过程用来发现多重原因。我们很少看到只由一个根本原因造成的失败。保存事件日志并定期回顾以发现重复出现的问题和主题。
既然已经讨论了应该做什么,那么让我们回到没有机会研发此类系统的情况。韦克和萨克利夫为幸运的机构提供了一个解决方案,帮助它们构建有效扩展且不经常出现故障的平台[3]。为满足本书的需要,我们对该方案稍加修改并描述如下。
■ 关注失败 ——做法就是监控产品和系统并及时报告错误。有人会认为,成功使人目光狭窄并且盲目自大。要控制由此而产生的自满情绪,企业需要把系统故障完全透明。应该广泛发布报告并经常讨论,如在每日例会上讨论平台运作。
■ 拒绝简化解释 ——不采取任何想当然的措施,寻求来自不同来源的输入。不要试图将失败转化为预期的行为并表现出貌似健康的偏执狂。人们倾向于把小变化解释为“常态”,而它们很可能在早期就预示了未来的失败。
对操作的敏感性——查看分钟级的详细数据。包括实时数据的使用并进行持续评估和不断更新。
■ 坚守弹性承诺 ——通过轮岗和新技能培训,培养全方位的能力。 eBay 的前雇员可以证明数据库管理员( DBA )、系统管理员( SA )和网络工程师都曾在运维中心轮岗。此外,一旦修复,团队应迅速重新进入戒备状态,准备应对下一个
挑战。
■ 尊重专业经验 ——在危机事件中,从领导的角色转换为拥有最专业知识的个人来处理这个问题。考虑围绕危机管理提高能力,如在运营中心设置“值班技术官”。
不要漠视前车之鉴,因为那是做出积极改变的最大机会源泉。建立运转良好的事后分析过程,从错误中提炼出一丝一毫的经验教训。如果不花时间对事件进行事后分析,找到真正的根本原因,并吸取经验教训以避免犯同样错误,那么失败注定会再次发生。我们的逻辑是,错误不可避免,但不能犯相同的错误。如果找不到性能差的查询,结果直到进入生产环境并导致网站中断才发现,那么就必须要找到真正的根本原因并修复。在这种情况下,问题的根本原因已经不仅是查询性能不好,还包括允许该查询进入生产环境的过程和人员。如果有个精心设计、很少出故障的系统,即使在极端的扩展需求下,实践组织“正念”,接近数据以便更好、更容易地发现未来的故障。在这种情况下很容易陷入自满的感觉中,应该对可能发生的不同故障进行假设和头脑风暴。这里的关键是要从错误和成功中吸取经验教训。
规则 28——不靠QA发现错误
内容: 利用 QA降低产品交付成本,提高技术吞吐量,发现质量趋势,减少缺陷,但不提高质量。
场景: 任何可能的机会下,通过专人聚焦测试而不是写代码以提高效率。利用 QA从过去的错误中学习。
用法: 每当测试活动获得超过一个工程师的价值输出时,就雇用一个 QA人员。
原因: 降低成本,加快交付速度,减少缺陷重复。
要点: 因为系统质量无法测试,所以 QA并不会提高质量。如果使用得当,可以提高生产力,同时降低成本,最重要的是,可以避免缺陷率的增长速度超过快速雇用期间的组织增长率。
▲不要过度依赖测试
为了启发思考和讨论,规则28有点文不对题。当然,有一个团队负责测试产品并发现缺陷是有道理的。问题是不应该仅仅依靠这些团队发现所有缺陷,这好比航空公司只靠飞行员安全着陆。这个观点的核心基于一个简单的事实:测试无法成就系统质量。测试只能发现研发过程中带来的问题,其结果是找回被摧毁的价值。比较罕见的情况是测试或执行测试的团队发现了未开发的机会,并由此创造附加价值。
不要误解—— QA 在技术团队中起着重要的作用。当公司以令人惊人的速度快速增长并且需要扩展系统时, QA 甚至起着更为重要的作用。 QA 的主要作用是以较低的成本帮助发现产品的问题,这与工程师执行的任务相同。从该角色中获得的两个重要好处是提高工程速度和增加缺陷检出率。
QA以与工业革命降低制造成本和增加产量相同的方式得到了这些好处。通过把工程过程流水线并且使工程师主要聚焦在构建产品(当然还有单元测试)上,在测试过程的建立和拆除上花费更少的时间。工程师现在每天可以有更多的时间专注于构建业务应用。因此我们通常会看到每小时的产出量和每天的产出量都增加了。以静态成本取得较高速度的结果是单位成本下降。此外,一个好的 QA 团队的单位人力成本通常低于技术团队,这又进一步降低了成本。因为检测团队集中精力发现缺陷并且得到激励,所以他们在发现自己的代码(如许多工程师写的)或者身边很要好的工程师朋友的代码问题时,没有任何心理负担。
▲ QA人员的价值在哪里?
什么时候聘用 QA人员
当通过聘请QA人员可以获得一个或多个工程师的生产效率时,就应该雇用一个QA人员。这笔账相当容易算。如果有11个工程师,每人大约花费10%的时间在测试上,这相当于一个QA人员的工作量,通过雇用一个QA人员,你可以取得等价于1.1个工程师的生产效率。通常,这个QA人员的成本比工程师要低,所以你是以0.8或0.9个工程师的成本得到了1.1个工程师的工作价值。
这些观点并不反对在运转良好的敏捷过程中工程师和QA人员互相配合。事实上,在许多实施案例中,我们都建议采用该方法。但分工仍然有价值,通常会达到降低成本、提高缺陷发现率、增加吞吐量的目标。
但QA团队最大的尚未阐明的价值体现在超高速增长公司。这并不是说该价值在静态公司或低速增长公司里不存在,但对每年翻一番(或更多)的技术团队它变得更加重要。在这些情况下,标准难以执行。在公司内任期较长的工程师没有时间跟上和执行现有的标准,甚至没有时间来发现对新标准方面的需要,以满足扩展、质量或可用性方面的需求。在每年翻一番的情况下,从第三年年初开始,半数“经验丰富”的团队中成员平均只有一年或更少的公司经验!
这就给我们带来了问题,为什么这个规则会出现在本章?想象一下在一个环境里,管理者花近一半的时间来面试和招聘工程师,半数(或更多)工程师在该公司的工作时间少于一年。想象那些现有的经验丰富的工程师将花多少精力来指导新入职工程师学习源代码管理系统、构建环境、生产环境等。在这样的环境里,几乎没有时间来验证代码构建得是否正确,并且发布到QA环境中的错误数量(理想情况下不是生产环境)明显增加了。
在这些环境中, QA 的工作是从质量角度告诉团队正在发生什么事情以及在什么地方发生,这样,工程团队就可以适应和学习。 QA 成为一个工具,有助于团队了解哪些错误反复出现,这些错误发生在什么地方以及理想情况下团队如何在未来避免这些错误。 QA 很可能是唯一能看到这些问题反复出现的团队。
如果新工程师没有机会看到失败及其所带来的影响,他们不仅可能会继续犯错,还容易养成犯这些错误的习惯。更糟的是,他们很可能把这些坏习惯教给刚入职的新工程师。一开始略微增加的缺陷率,会逐渐增加并变成恶性循环。而当噩梦在眼前即将发生时,所有的人都在四处奔跑,试图发现质量噩梦的根源:从过去的错误中吸取教训!
诸如代码审查和测试驱动的开发(TDD)之类的技术,可帮助工程师产生高质量代码,在达到 QA 之前发现缺陷。与同行进行一对一的代码审查,有助于工程师在初始研发过程中发现和纠正错误。测试驱动的开发是一种方法,由工程师开发自动化测试用例(测试用例定义新的功能),然后产生可以通过测试的最基本代码量。 TDD 在提高代码质量的同时可以提高生产效率。这些技术有助于在该过程尽早把质量内置在软件中从而减少返工机会。
QA 必须致力于确定在成长型组织中哪里存在着反复发生的问题,并搭建环境来讨论和解决这些问题。 最后, QA 最重要的好处是:有助于团队从技术故障中学习。 工程师产生缺陷,而 QA 有助于降低风险。要理解 QA 无法测试系统的质量,而且不愿意自己作为研发安全检查的角色,就像在棒球比赛中,站在接球手后面来捕获他们未接到的球一样,优秀的 QA 团队致力于发现技术团队中那些会导致后期质量问题的系统性故障。其价值远远超出了绘制燃尽图以及确定查询 / 修复比率的重要性;这涉及挖掘和发现问题的主题及其来源。一旦确定下来,他们就会提出解决问题的想法。
规则 29——不能回滚注定失败
内容: 必须具备代码回滚的能力。
场景: 确保所有版本的代码都有回滚能力,在准生产或者 QA环境演练,必要时在生产环境用它来解决客户的问题。
用法: 清理代码并遵循几个简单的步骤以确保可以回滚代码。
原因: 如果没有经历过无法回滚代码的痛,还继续冒险地 “修改-发布”代码,那么你可能会在某个时刻体会到这种痛苦。
要点: 应用过于复杂或者代码发布太频繁所以不能回滚,这个借口无法接受。稳健的飞行员不会在飞机不能着陆时起飞,明智的工程师不会发布不能紧急回滚的代码。
▲ PayPal惨痛的教训
如果要为下个规则营造合适的气氛,那么大家应该在深夜围坐在篝火旁讲恐怖故事。我们要讲的是经典的恐怖故事,包括那些在屋子里听到了可怕声音但不出去的人。那些忽略了所有警告信号的蠢人就是我们自己。
时间回到2004年 10 月 4 日的那一周。 PayPal 技术团队刚完成聚焦重要架构调整的最复杂开发周期。这些变更的目的是拆分几乎是单体的 CONF 数据库,该数据库包含了 PayPal 用户账户以及在 PayPal 系统上不可或缺的同步资金收发。
多年来,PayPal不曾考虑过拆分单体数据库。但交易和用户账户的增长惊人(一直到 2004 年, PayPal 服务都持续稳居增长最快的前五名),摩尔定律允许该公司通过购买更大和更快的系统来扩展,而暂缓数据库架构的重大拆分。在 2004 年,公司的数据库 CONF 运行在 Solaris Sun Fire 15K 上,该系统配置了 106 个 1.35 GHz 处理器和 18 块系统板。即使拥有这种比较大的处理能力(当时),该公司也很快就耗尽了系统容量(当时是 Sun (现在的 Oracle )可用的最大系统)。虽然 Sun 已经宣布会有更大的服务器 E25K ,但是负责技术的高管们( eBay 高级副总裁和首席技术官马丁·阿伯特, PayPal 首席技术官盖革,以及 PayPal 技术副总裁与架构师迈克·费舍尔)认为未来的增长不能再依靠向上扩展了。
因为PayPal的产品始于早期移动设备上的转账, PayPal 的产品负责人强烈地感觉到账户之间的任何转账都需要“实时”发生。例如,如果马丁想给迈克转 50 美元,交易要想成功,必须立即从马丁的账户转出资金,同时把资金立即转入到迈克的账户。如果转出或转入失败,就需要事务回滚。不管这种做法是否真正具有差异化竞争力,但绝对源于支付行业的其他机构(如传统银行)的典型实践。这些解决方案把资金的转出和转入交易分开。借方首先在马丁的账户上转出资金。这可能是立即记录借记的金额或未决交易的通知。发给迈克账户的通知可能会发生在从马丁账户转出资金的时间点。如果发出某些通知,它通常是单个代表入站未决事务的过程。一些未来的借贷过程——通常不会变成同步交易,而会形成多个异步交易。第 8 章会讨论 PayPal 团队如何解决这个问题。现在,让我们听听时任 PayPal 首席技术官盖革对实施本规则的看法。
“ PayPal 从其初始阶段开始,一直就一边发布新代码,一边计划好在生产中发现任何错误时进行修正,然后再发布。这种做法在版本 24.0 之前从来没有给业务带来任何重大的问题。然而,这种做法与其当时的母公司 eBay 的实践截然相反, eBay 始终确保在代码进入生产环节后随时可以回滚,”盖革解释道。
“ PayPal 的技术团队认为,始终能够回滚到任何版本的代价远远超过了该过程的价值。该过程的代价建立在每个版本成本的基础上,回滚比修正后再发布的概率要低。经验告诉我这类分析有两个失败的地方,随后会深入讨论。版本 24.0 的发布带来了一场难以拯救的大灾难。我们根本就无法处理美国白天高峰时段的交易。因为我们试图解决与该版本相关的问题,所以灾难至少持续了三个交易日。那三天我们未能对用户履约。”
eBay在2004年10月14日向其用户发布了道歉信[4]:
过去几天,你们中的许多人经历了PayPal的使用问题。首先我们想就此表示抱歉,因为影响了您的交易活动,对许多人来说,这是您的业务。
正如我们早些时候沟通的那样,最近出现的访问网站和使用PayPal功能的问题,是因10月8日星期五为了升级网站架构发布新代码带来的意外结果。账户数据和个人信息从未出现问题,许多用户在使用PayPal付款和发货功能时遇到了困难。为能尽快恢复正常服务,来自PayPal和eBay的两个技术团队在夜以继日地工作。
PayPal的功能已经恢复正常,无论在eBay平台还是其他地方,PayPal用户已经能够恢复正常的交易活动。展望未来,我们的技术团队将继续专注于确保为PayPal平台提供最高标准的可靠性和安全性。
感谢您在此过程中的耐心。提供优质服务是PayPal的当务之急。虽然在过去的几天里我们没有达到您或我们自己的期望,但是我们期待有机会能重新获得您对我们服务的信任。
您真诚的朋友,
eBay总裁兼首席执行官梅格·惠特曼
eBay全球在线支付高级副总裁兼PayPal总经理马特·班尼克
eBay负责技术的高级副总裁马丁·阿伯特
▲回滚的价值是不可预计的,成本却很低
盖革继续说道,“尽管完成了与 eBay 回滚能力保持一致的专题项目,但是实际上由此带来的网站问题好像并不多,为任何版本启用回滚代码的成本也不高。在两周内,我们就找到了可以在软件变更之前通过修改数据库模式,从而验证向后兼容性的方法。现在讨论前面提到的故障分析:( 1 )从任何版本回滚的成本几乎总比你想象的低,( 2 )能够回滚的价值不可估量。只需要有一次重大的失败,你就会感同身受,但我建议不要冒这种风险。”
以下几点为我们和许多其他团队提供了回滚能力。正如你所预期的,大部分回滚的问题出现在数据库中。通过梳理应用,清理悬而未决的问题,然后坚持一些简单的规则,每个团队都应该能够回滚。
■ 数据库结构的变更仅可以增加 ——只应该增加而不删除列或者表,直到下一版代码发布,它明确不再依赖于这些列。这些标准一旦实施,每个版本都应该有一部分专门致力于清理以前发布但现在不再需要的数据。
■ 数据库变更脚本化并经过测试 ——代码发布涉及的数据库变更必须提前写好脚本,不能采用手工操作。这应该包括回滚脚本。原因是:( 1 )团队需要在 QA 或者准生产环境中测试回滚过程,以验证它们没有漏掉什么将阻止回滚的内容,( 2 )需要在一定负载条件下测试脚本,以确保当应用使用数据库时仍然可以执行脚本。
限制应用中SQL查询的使用——开发团队需要纠正所有含糊不清的 SQL 查询,去除所有的 SELECT * 查询,并且为所有的 UPDATE 语句添加列名。
■ 数据的语义变化 ——开发团队不能改变版本中数据的定义。一个例子是目前作为状态信号量的票务表中的一列,状态信号量表示三值:已分配、固定、关闭。新版本的应用不能添加第四个状态,直到先发布了代码来处理新状态为止。
■ 上线 / 下线 ——应用应该有一个基于外部配置的框架,该框架允许特定用户可以访问代码路径和功能。该设置可以在配置文件或数据库表,允许基于角色和随机百分比的方式控制访问。这个框架允许针对一组有限的用户进行 beta 测试功能,并允许在某功能出现重大错误的情况下,快速删除该功能的代码路径,而不必回滚整个代码库。
我们吸取了痛苦但宝贵的教训,留下的伤痕如此之深,以至于我们再也没有发布过一次无法回滚的代码。即使辗转到了其他的团队和工作岗位,该要求一直与我们如影随形。正如你所看到的,前面的指导方针并不复杂,任何团队都可以直截了当地应用这些规则并形成回滚能力。确保任何变更可以向后兼容所带来的额外研发和测试投入,是投资回报率最大的工作。
总结
本章一直在讨论学习。 积极学习,从别人的错误中学习,从自己的错误中学习,从客户那里学习。 做学习型组织和学习型个体。不断学习的人和组织永远领先于那些不愿意学习的人,正如伟大的查利 ·琼斯( 9 本书的作者和无数奖项的获得者)所说的那样,“除了遇到的人和读过的书外,在十年内你还是你。”我们希望引申他的说法,一个组织的明天将和今天相同,除非能从客户、自己和其他人的错误中吸取经验教训。
注释
1.Charles Perrow, Normal Accidents (Princeton, NJ: Princeton University Press, 1999).
2.Todd R. LaPorte and Paula M. Consolini, “Working in Practice but Not in Theory:
Theoretical Challenges of igh-Reliability Organizations, ?Journal of Public Administration Research and Theory, Oxford Journals, http://jpart.oxfordjournals.org/content/1/1/19.extract.
3.Karl E. Weick and Kathleen M. Sutcliffe, “Managing the Unexpected,” http://high-reliability.org/Managing_the_Unexpected.pdf.
4.“A Message to Our Users—PayPal Site Issues Resolved,” http://community.ebay.com/t5/Archive-Technical-Issues/A-Message-To-Our-Users- PayPal-Site-Issues-Resolved/td-p/996304.
本文选自架构真经:互联网技术架构的设计原则(原书第2版)一书,由马丁·阿伯特、迈克尔·费舍尔著,陈斌翻译。
本书是《架构即未来》的姊妹篇。全书共分13章,用成功互联网产品公司首席技术官和企业家的故事,引出了对构建可扩展的产品至关重要的50条规则,可帮助软件研发人员、技术运维人员和管理者修复或重新架构现有产品,了解关于扩展的佳实践并有计划地实施,还可以帮助建立一套架构原则以推动未来的研发。
购买本书直达入口,请点击"阅读原文"。
本公众号编辑部维护读者群之架构群,邀请了坐馆老司机李艳鹏、曲健、伟山、史海峰嘉宾等参与交流。加群请在公众号回复: 架构群。
技术琐话
以分布式设计、架构、体系思想为基础,兼论研发相关的点点滴滴,不限于代码、质量体系和研发管理。