知识卡片

任务分解为什么能提升性能,以及拆分过细为什么反而降低性能

结构图卡

内容

单纯靠加机器(任务分配)来扩展性能,收益会随着业务复杂度上升而递减——业务简单时1台扩到10台可能提升8倍性能,业务复杂后1台扩到10台可能只提升5倍,因为单台机器处理复杂业务的效率本身在下降。这时需要用另一种手段:任务分解,把一个大一统的复杂业务系统拆成多个更小、更简单的子系统(如微信后台拆成接入、注册登录、消息、LBS、摇一摇、漂流瓶等子系统)。任务分解本身既不减少功能也不减少代码量(甚至可能因为要新增系统间接口调用而增加代码量),它能提升性能靠的是两个机制:一是简单的系统更容易做到高性能——功能越简单,影响性能的变量就越少,越容易精确定位并优化关键性能点;系统一旦复杂,不但难以找到真正的瓶颈,即使找到了修改起来也容易顾此失彼(提升了A点性能却意外拖累了B点)。二是可以针对单个任务做独立扩展——拆开之后哪个子系统先出现性能瓶颈,只需要优化或加机器给这一个子系统,其余子系统完全不用动,风险比改动整个系统小得多。但任务分解不是拆得越细越好:系统间调用要走网络,比系统内部函数调用慢得多,而完成一次用户请求所需要跨系统调用的次数会随着拆分粒度变细而急剧增加——拆成2个子系统只需要1次系统间请求,拆成4个子系统涨到3次,如果拆到100个子系统会暴增到99次。按一次网络请求耗时1毫秒、业务处理本身耗时50毫秒来估算,2个子系统处理一次用户访问总耗时约51毫秒,而100个子系统会飙升到149毫秒——业务处理性能本身是有上限的,任务分解能让实际性能逼近这个上限,但无法突破它,过度拆分反而会被暴涨的网络调用次数拖累,把原本该省下来的时间又搭进去。因此任务分解带来的性能收益是有一个合理粒度区间的,架构设计的关键功夫,就在于判断这个粒度该切在哪里。

结构图

flowchart LR
  A["拆分越细"] -->|优点| B["单个子系统更简单<br/>更容易定位和优化关键性能点"]
  A -->|优点| C["性能瓶颈局限在单个子系统<br/>可独立扩展,风险小"]
  A -->|代价| D["系统间调用次数指数级上升<br/>2子系统1次→4子系统3次→100子系统99次"]
  D --> E["网络调用远慢于系统内函数调用<br/>总耗时反而可能不降反升<br/>(2子系统约51ms → 100子系统约149ms)"]
  B & C & E --> F["任务分解粒度存在最优区间<br/>并非越细越好"]

参考来源

- 位置:《从零开始学架构》第04讲《复杂度来源:高性能》"任务分解"(源文件:_epub-src/OEBPS/text00000.html) - 结论依据:原文说明"简单的系统更加容易做到高性能……可以针对单个任务进行扩展……当各个逻辑任务分解到独立的子系统后,整个系统的性能瓶颈更加容易发现……如果系统拆分得太细,为了完成某个业务,系统间的调用次数会呈指数级别上升……系统拆分为 2 个子系统的时候,处理一次用户访问耗时为 51ms;而系统拆分为 100 个子系统的时候,处理一次用户访问耗时竟然达到了 149ms……任务分解带来的性能收益是有一个度的,并不是任务分解越细越好",直接支撑本卡片结论。 - 原始内容:如果系统拆分得太细,为了完成某个业务,系统间的调用次数会呈指数级别上升,而系统间的调用通道目前都是通过网络传输的方式,性能远比系统内的函数调用要低得多……系统拆分为 2 个子系统的时候,处理一次用户访问耗时为 51ms;而系统拆分为 100 个子系统的时候,处理一次用户访问耗时竟然达到了 149ms。