一.什么是可扩展性?
Scalability is the property of a system to handle a growing amount of work by adding resources to the system.
可扩展性,意味着能够通过向系统添加资源的方式应对不断增加的工作量。而加资源有两种方式:
纵向扩展(Vertical scaling):即提升单机配置,对单台机器加内存、处理器、硬盘等硬件资源。投入足够多的预算,就能砸出一台配置豪华的服务器
横向扩展(Horizontal scaling):即加机器,数量上从一台扩展到多台,多服务器形成拓扑结构。投入足够多的预算,就能拥有一个机房,甚至遍布全球的数据中心
对于系统设计而言,可扩展性要求系统能够将加入进来的更多资源(如多核、多机)利用起来
二.贯穿系统设计的可扩展性斗争
一个用户请求从客户端出发,经过网络传输,达到 Web 服务层,接着进入应用层,最后抵达数据层:
对应到系统设计中的各个逻辑层:
途径的每一层都有其特定的可扩展性模式:
最后形成了如此复杂的系统架构:
其运作机制如下:
客户端查DNS得到服务对应的 IP 地址,可能指向位于 Web 服务之前的负载均衡器,也可能是CDN,就近提供对象存储中的静态资源
涌向 Web 服务的请求被负载均衡器(比如反向代理)按照既定策略分发给相应的 Web 服务器,进入应用层
请求到达应用层后,经过Service Discovery、Service Mesh等服务查询机制找到目标微服务,开始处理请求
数据请求会通过一系列读/写 API 最终转到数据层,异步的操作还会进入消息队列排队,但最终都会抵达数据层
对热点数据的请求会被数据库之前的缓存层挡下来,其余的落到数据库,可能是经过分库分表、反范式优化,并由复制机制保证数据一致性的 SQL 数据库,也可能是查询性能更好的NoSQL 数据库,抑或对象存储
其中,许多模式在解决一些问题的同时,又带来了一些新的问题,因此,在系统设计中,大到 CAP 的抉择,小到分发策略的制定,总在不停地进行权衡取舍
三.商业化背景下的可扩展性要求
至此,系统设计中常用的扩展性模式都已经梳理清楚了
回过头来再看可扩展性:
可扩展性,意味着能够通过向系统添加资源的方式应对不断增加的工作量
单从定义来看,一个系统只要能把加进来的资源利用起来,进而有能力承担更多的工作量,那它就是可扩展的,这也确实是可扩展性的基本要求
然而,实际场景中(商业化背景下),我们对可扩展性提出了更高的要求:
很多时候,无脑加资源确实能解决问题,但对于可扩展性而言,烧钱是可耻的:
Well, you can just throw hardware at the problem which is the thing that’s thrown around our industry a lot. And I think it’s a little bit of a shame, because it is just effectively like burning money.
也就是说,要求系统不仅能利用,而且要尽可能高效地利用加进来的资源,而不只是一味地靠加资源实现线性扩展
而利用率的衡量标准通常是单笔交易的成本(在非交易系统中可能是其它类似的业务指标):
单笔交易成本 = 总成本 / 交易量
其中,成本分为固定成本和可变成本两部分:
固定成本:前期工作和基础设施、摊销费用、资本成本、经营成本等
可变成本:能否按需使用、批量是否有折扣、确保资源可用(维护管理等)
因此,在商业化背景下,可扩展性要回答的问题是,加 1 台机器进来,能多支持多少业务量:
A typical question I would ask of anyone is if you add another node to your system how many more units of work or transactions or whatever do you get out of that.
不只是确信加机器能应对更多的工作量,还要精确地知道“更多”是多少,进而优化成本,精益求精