2.3 服务应该有多可靠
上一节讨论的示例表明,当你考虑可靠性时,通常需要考虑许多事情,而当你试图确定每个组件到底需要多高的可靠性时,事情会变得更加复杂。第4章将更深入地讨论一旦你有了SLI,如何选择好的SLO目标。但是在你有这些数据或者尝试之前,还有一些可靠性的概念需要了解。
如果我们同意是用户决定了服务的可靠性,那么在选择正确的目标时需要考虑的是用户。这意味着你必须找出一些方法来确定用户的感受和他们需要什么。对于面向客户的服务,你只需查看采用率或关于产品的评论。对于内部服务,可以从用户越过许多层,这可能会涉及更多,但最终仍可能依赖于度量或询问人们对你的服务的可靠性的感受。然而,询问别人可能是一项复杂的任务。
在征求用户反馈时,需要记住的最重要的一点是,像调查这样的方法通常会提供嘈杂的数据。如果你允许受访者自行选择,则根本不知道样本集会有多偏颇。此外,用户通常将调查视为一种烦恼,即使他们选择填写调查问卷,也不会花太多时间认真考虑自己的回答。人们倾向于只选择“好”或“坏”,而不会考虑真正的细微差别。
虽然需要投入更多的资源,但更好的选择是类似面试的过程。与你的用户坐下来,不管他们是付费客户还是其他内部团队,并就他们目前如何看待你的服务的可靠性进行对话。如果你有一个专门的客户支持部门或用户体验团队,你就有更多的资源可以让你坐下来聊聊天:他们很可能每天都会与外部用户进行这种类型的对话,为你的外部用户的体验考虑。第14章将更深入地与用户交谈。
除非你已经有非常清晰的商业分析来指导你的期望值,否则你不能仅仅靠猜测来判断你的服务需要多可靠。而且,除非你直接问他们,否则你不知道你的用户需要服务有多可靠。在本书后面的各个章节中,我们将介绍许多可以用来帮助你解决这个问题的数学模型。但首先,除了用户的希望、梦想和愿望之外,你还需要记住其他一些事情。
2.3.1 100%是不必要的
本书的一个主要信条是100%是不可能的。
我们购买或与之交互的许多服务,要么偶尔失败,要么预期在一段时间后失败。
一个许多人可能熟悉的例子是,有时汽车在第一次尝试启动时启动不了。你转动钥匙,听到发动机开始转动,但它只是发出一点点咯吱声,一个完整的燃烧循环实际上从来没有开始过。如果这是一个永久性的问题,它将被视为真正的故障,你必须采取措施,如更换燃油泵。但这种情况只是偶尔发生。只要汽车大部分时间第二次启动时没有问题,人们就不会急于买辆新车。这是一个功能可用性的例子,汽车能够启动,但并不是每次都能启动。
如果你的车每次第一次尝试时不能启动,它就不是100%可靠。然而,只要它大多数时间在第一次或第二次尝试时能够启动,就足够可靠了。如果一家汽车制造商基于目前的设置没有失去当前或未来的业务,那么他们并不会花费资源开发更好的燃油泵[1]。
让我们考虑另一个例子。也许你有一块很喜欢的手表。它很时尚,也很合身,但手表可靠的一个主要表现是它能正确地显示时间。这只表很容易在时间上落后,但它可能每几个月只落后一min左右。因此,手表并不是完全可靠的,但如果你只需每隔几个月修正一次,那就没有问题。
手表不可靠的另一个表现是它比真实时间晚了一两分钟,但在这个状态下却保持稳定。这款手表并不完全可靠,因为它有一个可以被描述为“让用户发现正确时间”的功能,而且它并没有完全实现这一点。不过,只要手表一直以或多或少相同的方式不可靠,它的主人就不会为此有太多烦恼。他们只需学会在手表上加上一两分钟,这对大多数人来说已经足够了。这个例子说明了跨多个事物的数据同步性不一定总是完美的。
再看一个例子。有时候,当你点餐时,并不总是得偿所愿。如果你在一家餐馆,可以让他们重做,但是如果你点的是外卖,那就不那么容易了。假设你从最喜欢的当地比萨店点了一个大的意大利香肠比萨。当送货上门时,原来是一个没有配料的普通奶酪比萨。
幸运的是,你也喜欢奶酪比萨,所以选择接受,而且还很享受这个比萨。这种错误可能会让你暂时感到些许困扰,但不会让你停止从这家比萨店点餐,除非这种情况经常发生。只要正确的订单占总订单的比例仍然很高,你就仍然是一个满意的客户。这个例子说明数据质量或正确性并不一定总是完美的,尤其是如果你可以确保在发生这些错误时,只需降低到用户仍然可以接受的状态。或者,按照在餐馆里重做的例子,只要用户能够很容易地重试他们的请求,就能接受偶尔失败。
类似地,假设你在这个比萨店点餐的大部分时间里,都会在30~40min内收到订单,这让你非常高兴。然而,每10个订单有一个大约需要1h才能到达。当你要等整整1h的时候,你不会特别喜欢它,但是因为比萨很好吃,而且90%的时间它都会很快到达,一天结束的时候,你真的不太在乎。你作为用户,只是希望这是工作方式的一部分。这个例子说明服务延迟也不一定总是可靠的。
本书是关于如何保持计算机系统的可靠性的,但这些概念实际上适用于几乎所有的东西。失败的不仅仅是软件:一切都会在某个时刻失败。因此,建立一种期望值和一种为之做好准备的文化,并尽可能多地让用户接受失败。
2.3.2 可靠性是昂贵的
为了使可靠性接近100%,所需的资源会以比线性更陡峭的曲线增长。因为实现100%的完美是不可能的,你可能花费了无限的资源却永远达不到。
可靠性在很多方面都很昂贵。第一个也是最明显的就是经济问题。要构建能够容忍失败的系统,你需要很多东西。这并不意味着你的整个系统都是分布式的。不管你是在自己的数据中心的硬件上运行服务,还是通过云提供商,或者两者都运行。如果你需要服务是高可用性的,你将在追求这个目标的过程中花费更多的费用,因为你需要在不止一个物理或逻辑位置部署服务。
此外,还需要你的系统具有严格的测试基础设施。如果在发布之前没有正确地对更改进行审核,则更可能遇到失败和不可靠的情况。这可能意味着从QA和测试团队到测试环境和适当的新技术的一切。所有这些都是好的,而且应该存在于任何成熟的软件工程中,但它们也要花钱。你希望它们越全面,就需要更多的人和计算资源。
除了经济成本,还有人力成本。例如,假设你希望在30天的时间内达到99.99%的常见可靠性目标。此目标意味着在这30天内,你只能在4min32s的时间内不可靠[2]。这进一步意味着,任何轮值此服务的人都需要有秒量级的响应时间。如果随叫随到的工程师只需要5min就可以到他们的笔记本电脑前开始诊断,那么你就不可能有99.99%可靠的服务。那些为99.99%的目标服务的人需要时刻保持笔记本电脑在触手可及的范围内,他们将不得不协调他们的通勤与他们的副手或备份,在他们轮班的时候将不能做看电影或遛狗等事情[3]。
根据你的服务,这可能对于你的工程师是完全合理的要求。但是,你能以人性化的方式做到这一点的唯一方法是确保你有很多工程师能随叫随到,这样他们就不必经常遵守非常严格的响应时间。但这种超负荷可能是让工程师辞职的一个原因。此外,你几乎肯定需要一个7×24h轮值的方法,让人们分布在世界各地,所以他们只需要在醒着的时候随时待命。这导致需要全球分布的办公室和向大量员工支付费用。
除了所有这些因素之外,还有一些简单的数学方法可以帮助我们理解这一点。例如,当你考虑从99.9%可靠性提高到99.95%可靠性时,直觉可能会告诉你,可靠性从99.95%提高到99.99%几乎是一样的,但这并不是数学计算的实际结果。
99.9%的可靠性意味着0.1%的不可靠性,而99.95%的可靠性意味着0.05%的不可靠性。从0.1%到0.05%的变化系数为2:
同时,99.99%的可靠性意味着0.01%的不可靠性。这意味着如果可靠性从99.95%上升到99.99%,不可靠性就从0.05%变化到0.01%。变化系数为5:
因此,从99.95%到99.99%的变化是从99.9%到99.95%的2.5倍。实现这一目标所需的资源至少将按比例增加。这就是为什么追求一个永远接近但永远达不到的目标,最终会让你付出超出计划的成本。
在本书的后面,我们将更深入地了解这一切是如何运作的,现在我们要注意的是,当你试图接近一个100%可靠的系统时,它会以许多不同的方式变得越来越昂贵。不管怎样,你的用户并不需要服务100%可靠,所以不用花费太多的资源来达到这个目的。
2.3.3 如何看待可靠性
尽管如此,我们还剩下一个首要问题:“你应该如何考虑可靠性?”总的来说,这里没有一个答案,因为这取决于各种因素。
我们可以说“尽你的用户所需的那样可靠。”这句话没有错。问题是,很难确切地知道这一级别是什么,特别是因为用户的可接受限制会有所不同,而且这些限制会随着时间的推移而变化。
更进一步说,我们可以说“只要足够可靠,你的业务就会增长。”但我也不确定这是否完全正确。不存在一个完美的公式来确保服务是可靠的。此外,你的服务只能像你的上游服务一样可靠,这通常包括互联网和消费者连接的可靠性。
这个问题的答案要微妙得多。SLO是用来改变事情的,它可以适应你当前的现实和你的现状。有时候,你应该抓紧时间,严格执行你的错误预算。有时你会经历黑天鹅事件,不得不暂时忽略数字告诉你的认知。不管怎样,查看数据都会引发讨论。
不要忘记,整个基于SLO的方法只是一种以新的方式收集新数据的方法,并使用这些数据做出正确的决策。服务应该有多可靠的问题永远不会有一个单一的答案。