从蛋糕店的例子,学习软件系统设计

2023年9月3日

💎 加入 E+ 成长计划 如果你想要透过更深入、更具系统性的内容来成长,或是想要有社群一同交流,欢迎

本篇最早收录于《ExplainThis 全端双周报》第八期

系统设计现在基本上是程序员面试必考的问题。假如你对系统设计没有概念,让我们透过这篇文章,用蛋糕店的例子带你理解在软件系统设计时要考量的点。

假如今天你是位手艺了得的蛋糕师傅,你决定自己出来创业开蛋糕店。一开始你只有自己一个人,所以什么都要自己来,需要自己买材料、做蛋糕、顾店等等。显然假如只有自己一个人,当客人一多就会忙不过来。这跟软件系统一样,假如只有一个单机服务器,流量一大就会有撑不住的状况。

如何扩展?

这时就要思考如何规模化。一种方式是你每天喝红牛,让自己保持满血状态一个打十个;在系统设计上这叫垂直扩展,就是把单一机器的性能提升,让机器能承载更大的流量。然而就像人喝红牛还是有个极限,单一机器升级也是有其极限所在。因此多数时候,你会需要考虑水平扩展。

所谓的水平扩展是指多加机器,来乘载更大的流量。在蛋糕店中,你可以多雇用更多人,让每个人分担你的工作量,这样你就不需用每天灌红牛来一打十。然而,当你雇用人来帮你分担工作,你就需要确保每个人的工作量平均,才不会有人很闲,但有人操得要死做后离职。

选择水平扩展的方式也是如此,当你有多台机器时,你要确保机器能平均分配到要处理的流量,才不会有的机器闲置没在运作,但是有的机器处理量爆多导致应付不来。在系统设计中,我们会加入平衡负载器 (Load Balancer) 来解决这件事,透过平衡负载器,能够有效让机器平均分担要处理的量。

从蛋糕师傅晋升蛋糕店长的你,如今顾了人也确保大家不会太闲与太操,好像就可以安心退居幕后了? 当然这样如意算盘就打得太早,要规模化蛋糕店的事业,还有很多面向要顾及。举例来说,假如要把服务的客人从原本在某个县市,拓展到全国,就会遇到一些问题。

如何加快速度?

有些蛋糕店是不开分店,坚持要由本店制作再外送到全国各地,但是这会导致在比较远的客人,总是需要等很久才能收到订购的蛋糕。要解决这问题,可以在各地开分店,先把中央工厂做好的蛋糕送到分店,这样客人要订购时,就近把蛋糕送给在当地的客人。在系统设计上,(cache) 也是扮演相似的角色,在客户端要拿资料时,就近跟快取拿,而不用跟资料库拿,就能加快响应时间。

当蛋糕店生意越做越好,可能会想要多角化服务,像是许多蛋糕店现在也会同时卖饮料。而饮料是要现点现做的,当现场客人多的时候,就会遇到客人要等的状况。但在做手摇饮的现场通常混乱,要如何有效分派哪个工读生泡哪杯饮料呢?

很简单,现在许多手摇饮店,会依照客人点饮料的顺序,把要制作饮料的单号按照先来后到的顺序贴在成一排,先贴的单号会先被有空挡的工读生拿下来开始制作。只要该工读生一泡完手上那杯,就再去拿目前最前面的待做饮料。

如何有效处理繁多的任务?

在系统设计中,队列 (queue) 的机制,也是类似的方式。所谓的队列是先进先出,就像饮料店的做,先点的客人的单子会先被处理。在队列的机制下,就可以有效让多个 workers 去处理在队列中的任务,先放到队列的任务先被处理。而处理完手边任务的 worker,就去处理目前在队列中最前面的那个任务。透过队列的机制,让管理工读生们变得轻松许多。

在导入了许多机制后,蛋糕店运作相当顺利。然而很多时候意外是不可预知的,例如某个地区的店突然遇到店面被闪电打到,以至于电力系统出问题没办法正常营业。这时来店的客人就会扑空买不到蛋糕。总店为了解决这问题,导入一个即时监控与通报机制,当某间店有意外出现时,赶紧调派人手到现场把客人引导去邻近分店,让客人还是能就近买到蛋糕。

在软件系统中,也会需要有观测 (observability) 平台,来做即时记录 (logging),以及指标 (metrics) 监控,还有警报 (alarm) 发出,确保系统的整体稳定度,不会因为单一个服务挂掉而导致客户端请求没办法被处理。

有了监控报警系统,蛋糕店创始人对于整个品牌的稳定度感到放心许多,似乎可以好好退居幕后了。当然事情没那么简单,身为蛋糕店经营者,在运营蛋糕店时有非常多决策考量。接着我们将进一步从决策者的角度,来谈在真实世界的系统设计,有哪些重要的考量点。

🧵 如果你想收到最即时的内容更新,可以在 FacebookInstagram 上追踪我们