跳到主要内容

第 2 章 技术为什么会不断变化

副题:如果技术是决策的产物,变化就有原因

第 1 章把地图摊开之后,还有一个问题悬着:地图上为什么会有这么多技术?今天用单体,明天拆微服务;今天用 Session,明天换 JWT。如果技术只是名词,变化就是潮流;如果技术是决策的产物,变化就有原因。这一章,我们看技术为什么会不断变化——这不是技术史,而是一条贯穿全书的演进逻辑。

本章要建立的认知

  1. 技术变化不是潮流,是演进循环的必然结果——如果技术是决策的产物,变化就有原因;如果技术是名词,变化就是焦虑的来源。
  2. 每个技术都可以被放进同一个模板:业务复杂度上升 → 原方案无法承受 → 新技术出现 → 解决旧问题 → 带来新代价 → 新复杂度上升。
  3. 本书 4-27 章 = 这个循环的五次实景回放——读完本章,你能在任何一章开头问"这次循环的业务压力是什么、新技术是什么、代价是什么"。

2.1 本章要建立的认知

想象你入职一家新公司,接手了一个三年的老项目。README 里写的技术栈是 Spring Boot + MySQL + Redis,看起来挺标准。但你看代码时发现:Redis 用了三种不同的客户端,MySQL 里混着三种命名风格的表,同一个业务概念在三个地方有三个不同的名字。你问老员工"为什么这样设计",得到的回答通常是"当时业务需要"——但这五个字里藏着一部技术演进史。

"当时"的业务只需要支撑一百个用户,所以一个单体应用就够了。"当时"的团队只有两个人,所以口头对齐比文档高效。"当时"没有交易功能,所以数据一致性不是优先考虑的事。每一个"当时"都是合理的决策,但时间过去了,业务变了,原来的合理决策变成了今天的技术债。

这就是技术变化的真相:它很少是因为"新技术更好",几乎总是因为"旧方案无法承受了"

如果你把技术变化看成一条时间线——2000 年用 JSP,2010 年用 Spring,2020 年用云原生——你会觉得自己永远在追新,永远学不完。但如果你把技术变化看成一个循环,情况就完全不同。这个循环只有四个节点:

  • 业务复杂度上升
  • 原方案无法承受
  • 新技术引入
  • 解决旧问题,带来新代价

然后循环回到起点:新代价本身成为新的复杂度,推动下一轮变化。

这不是升级打怪,而是解决问题的方案成为新问题。缓存解决了读慢的问题,但带来了一致性的麻烦;服务拆分解决了协作的问题,但带来了调用链的复杂。每一个技术选择都在这个循环里占据一个位置,没有完美的终点,只有"当前方案还能承受多久"。

本章只建立这一个认知。下一节,我们用社区交易的五个阶段作为切片,看这个循环长什么样。


2.2 演进循环详解

2.2.1 循环四节点

图2-1 图稿占位
技术演进循环
复杂度上升→旧方案崩→新技术→新代价

我们用社区交易产品走一遍这个循环。它从"一个想法"开始,经历五个阶段,每个阶段的转折点都是同一个句式:原方案无法承受了。

节点 1:业务复杂度上升

这一步永远不是技术驱动的。你的社区交易产品刚上线时,整个产品只有你自己一个人在用,功能就是发内容和评论。这时候的业务复杂度极低:数据量小、并发低、功能单一、团队只有你自己。

然后用户增长到一百人。你开始收到"能不能卖点东西"的反馈。然后是一千人,有人投诉页面打开慢。然后是十万人,首页开始扛不住。业务复杂度上升的三个维度通常同时发生:用户量、功能数、团队规模。

图2-2 图稿占位
技术变化驱动因素
需求/并发/团队三个维度压垮旧方案

节点 2:原方案无法承受

这不是说旧方案不能用了。单体应用在小流量下跑得很好,手动发布在两三个人的团队里效率最高,直接查数据库在功能简单时足够快。

"无法承受"的意思是:继续用旧方案的代价超过了换方案的代价。页面加载超过 5 秒,用户开始流失;两个人手动发布还能应付,八个人就会互相覆盖代码;单机数据库能撑 1 万用户,但 10 万用户的查询会让 CPU 跑满。

关键认知:不是旧方案错了,是约束变了。在小流量约束下,单体是正确的;在大流量约束下,单体的正确性过期了。

节点 3:新技术引入

缓存不是为了"快"而引入的,是因为"慢到影响业务了"。CI/CD 不是为了"自动化"而引入的,是因为"手动发布在晚上 11 点出错太多次了"。服务拆分不是为了"微服务很先进"而引入的,是因为"三十万行代码里改一行要编译十分钟,团队排队等发布窗口"。

每一个技术选择都是节点 2 的答案。答案不唯一:读慢的问题可以用缓存解决,也可以用更好的索引解决,也可以先加一台只读副本。选择哪个,取决于你的约束——这正是第 5 章决策模型要展开的内容。

节点 4:解决与代价

新技术解决了旧问题,但代价不会消失,只会转移。

缓存让读变快了,但数据库和缓存之间的数据一致性成了新问题。事务让订单不会重复扣款了,但分布式事务的调试和回滚成了新问题。服务拆分让团队可以独立发布了,但服务之间的调用链、超时、重试成了新问题。

这就是循环的闭环:新代价本身成为新的复杂度,推动下一轮变化。缓存的一致性问题逼出了过期策略和更新模式;分布式事务的复杂度逼出了最终一致性和对账机制;调用链的复杂度逼出了链路追踪和熔断降级。

2.2.2 社区交易五阶段切片

下面四个切片是社区交易从"一个想法"到"规模化"的演进轨迹。每个切片只走"问题→技术→代价"三步,不展开技术细节——那些留给后面的章节。

切片 1:阶段 1 → 阶段 2(用户增长)

社区交易产品上线三个月,注册用户从几百涨破了 10 万。创始人发现首页打开越来越慢,数据库的 CPU 使用率经常在 90% 以上。

原方案:单体应用 + 直连 PostgreSQL,所有数据实时查询。

新技术:CDN(静态资源就近分发)、Redis 缓存(热点数据内存化)、数据库索引优化。

代价:缓存和数据库的数据不一致(用户改了头像,缓存里还是旧的);索引增加了写入开销;CDN 让调试变复杂(本地改代码,CDN 边缘节点还没刷新)。

这些问题在第 16 章完整展开。

切片 2:阶段 2 → 阶段 3(交易增长)

用户开始下单付款。第一次出现重复扣款,是因为用户点了两次"确认支付",后端没有做幂等。第一次出现订单状态混乱,是因为支付回调失败,订单卡在"待支付"状态三天。

原方案:普通接口直接扣款,没有状态机,没有幂等设计。

新技术:幂等令牌(同一笔支付只处理一次)、数据库事务(订单和支付状态一起成功或一起失败)、订单状态机(PENDING→PAID→SHIPPED→COMPLETED)、异步对账(每天凌晨比对支付渠道和本地订单)。

代价:事务让代码变复杂(回滚逻辑、死锁处理);异步对账引入了延迟(不是实时一致,是 T+1 一致);状态机让产品经理和开发者的沟通成本上升(每个状态变更都要对齐)。

这些问题在第 17 章完整展开。

切片 3:阶段 3 → 阶段 4(团队增长)

交易功能稳定后,团队从 1 个人变成 8 个人。发布频率从每周一次变成每天三次,但手动部署的失误率也在上升——上周有人在生产环境执行了测试脚本,数据库被清空了半小时。线上出问题时,8 个人同时 SSH 到服务器查日志,互相覆盖对方的排查进度。

原方案:手动打包、手动上传、手动执行 SQL;日志写在服务器本地文件里。

新技术:CI/CD 流水线(代码提交后自动测试、自动构建、自动部署)、日志集中采集(ELK 或等价方案)、监控告警(P95 响应时间、错误率)。

代价:CI/CD 需要维护构建环境和脚本;日志采集增加了存储成本;监控需要定义阈值和告警规则,阈值设错了就会半夜被叫醒。

这些问题在第 20-25 章完整展开。

切片 4:阶段 5 → ?(规模增长,伏笔)

代码库膨胀到 30 万行,编译一次要 10 分钟。前端改了一个按钮的颜色,需要等整个后端重新编译才能验证。团队分成三个小组,但所有代码在同一个仓库里,A 组的发布经常因为 B 组的代码冲突而回滚。

原方案:单体架构,所有功能在一个进程里。

新技术:服务拆分(按业务域拆成独立服务)、消息队列(服务之间异步通信)、事件驱动(状态变更通过事件广播)。

代价:分布式调试困难(一个问题可能要跨三个服务查日志);最终一致性(用户支付成功后,订单服务和库存服务的数据可能有几毫秒不一致);运维碎片化(以前只需要管一台服务器,现在要管十台)。

这一步,就是第 26 章要展开的内容。

2.2.3 循环的本质

回头看,这四个切片共享同一个逻辑:没有技术是为了"先进"而被选中的,每个技术都是"当时最合理的选择"。缓存不是比数据库"更好",是在"读慢到影响业务"这个约束下的答案。服务拆分不是比单体"更现代",是在"三十万行代码改不动"这个约束下的答案。

这就是第 1 章说的"决策地图":技术不是按时间排列的名词,是按约束排列的答案。约束变了,答案就变。

这个循环也是第 5 章决策模型的雏形。第 5 章会把"问题→候选方案→评价维度→选择→代价→演进条件"展开成九步,而第 2 章的循环是它的简化版:记住三个问题就够了:任何技术变化都可以被问——原来的方案承受了什么压力?新技术解决了什么?代价是什么?


2.3 每个技术都是一次循环

能力地图是"有什么",演进循环是"为什么有"。本书 4-27 章的每一项技术,都可以被放进下面这张表。表有四列:业务压力、引入的技术、代价、本书展开章节。

业务压力引入的技术代价/取舍本书展开章节
页面打开慢,数据库查不动缓存、CDN、索引一致性、失效策略、写入开销16
下单重复扣款,订单状态混乱幂等、事务、状态机复杂度、异步对账、沟通成本17
代码质量下降,上线频繁出故障测试体系、Code Review时间成本、流程摩擦18、20
手动发布风险高,回滚困难CI/CD、蓝绿/灰度发布基础设施成本、环境维护21-23
系统故障难定位,影响面不可控日志、监控、链路追踪存储与计算成本、阈值维护24-25
单体代码库膨胀,团队协作阻塞服务拆分、消息队列、事件驱动分布式调试、最终一致性、运维碎片26

这张表不是让你现在记住每一行的技术细节。它的作用是给你一个检验标准:读完本书后,你应该能给任何一个系统,填出它经历了哪些循环。

比如你现在维护的系统:它的缓存是在什么业务压力下引入的?当时有没有记录代价?如果约束变了(用户量再涨十倍),当前方案的代价会不会超过替换方案的代价?

不是背表,而是带着表去问问题。


2.4 与全书地图的关系

第 1 章给了地图,第 2 章给了"地图为什么一直在变大"。本书的七部分结构,本质上就是演进循环的五次实景回放。第一部分(第 1-3 章)是"地图和认知准备",让你先理解全栈是什么;第七部分(第 28 章)是"把地图变成你的能力",收束全书。中间五部分,就是循环的五次展开。

**第二部分(需求与设计,第 4-7 章)**对应循环的起点:业务复杂度刚出现时,怎么把需求翻译成技术语言,怎么做出第一个技术决策。第 4 章讲需求分析(识别复杂度),第 5 章讲技术选型(在约束下选择方案),第 6-7 章讲设计(把决策落地成表和接口)。

**第三部分(开发实现,第 8-15 章)**对应循环的"运行时":请求从浏览器出发,经过网络、服务端、数据层,最终回到用户。这是节点 3(新技术)的落地形态——缓存、CDN、事务、认证,每一项都在请求旅程中占据一个位置。第 15 章全链路收口,把 8-14 章的技术串成一张完整的旅程图。

**第四部分(性能、交易、安全与质量,第 16-20 章)**对应循环的"业务增长"阶段:用户多了、开始交易了、团队大了,原来的方案开始承压。缓存深化、交易系统、Web 安全、代码质量——每一项都是"原方案无法承受"后的回应。

**第五部分(发布与部署,第 21-23 章)**对应循环的"工程侧":新技术不仅要写出来,还要稳定地送到用户手里。CI/CD、部署策略、环境管理——这些都是节点 3 的另一半。

**第六部分(运维与迭代,第 24-27 章)**对应循环的"闭环":系统上线了,代价开始出现,怎么监控、怎么容灾、怎么演进。第 26 章回收第 2 章埋下的伏笔——当单体无法承受时,拆分和事件驱动成为选项。第 27 章把循环推向"迭代":新需求来了,重新走一遍全流程。

图 2-1(抽象循环)与图 26-3(架构演进)是母图与子图的关系。图 2-1 告诉你"所有技术变化都服从同一个模式",图 26-3 告诉你"这个模式在架构维度长什么样"。


2.5 小结:回到北极星

这一章只做了一件事:建立一个模型,用来解释技术为什么会不断变化。

  • 技术变化不是潮流,是演进循环——业务复杂度上升 → 原方案无法承受 → 新技术引入 → 解决旧问题 → 带来新代价 → 新复杂度上升。
  • 社区交易的五个阶段是这条循环的切片,本书 4-27 章是这条循环的逐次展开。
  • 没有技术是为了"先进"而选的,每个技术都是某个约束下的答案。约束变了,答案就变。
  • 第 26 章会收回本章的伏笔:当单体无法承受时,拆分和事件驱动成为选项。
  • 回到北极星:看懂系统 = 看懂它经历了哪些循环;解释设计 = 解释每次循环的压力、技术和代价;做出方案 = 判断当前节点该选什么技术。

如果你读完这一章能回答三个问题,就算懂了:你维护的系统当前在循环的哪个节点?上一个技术选择是在回应什么压力?它的代价现在还在承受范围内吗?

下一章,我们看这套逻辑如何在社区交易产品上展开——从一个想法开始,到五阶段故事线,你的地图上有了一个可以一直跟随的原点。