凌晨两点那条告警

去年秋天,一个做生鲜的朋友找我。凌晨两点,订单库连接数打满。报警群里刷了三十几条消息。值班的同学第一反应是流量涨了,加机器。没用。
第二天翻慢查询日志,一条 update 没走索引,单表六千万行。就这。
然后老板在周会上说了四个字:该拆了吧。我在旁边听着,心里咯噔一下。
想拆的冲动从哪来
很正常。系统一慢,人就想去动结构。好像把一个大盒子砸成十几个小盒子,速度自然就上来了。
但多数时候不是。单体应用的问题,九成出在数据层和人的协作上,不在部署形态上。那条慢 SQL,拆成微服务照样慢,甚至更慢——因为链路变长了。
还有一种更隐蔽的动机。团队从五个人变成四十个人,一个仓库里十个人改同一个文件,天天冲突。这时候你想拆,其实不是技术问题,是组织问题。康威定律说的就是这个意思:你的系统架构,最后会长成你公司沟通结构的样子。

边界画错比不拆更难受
真决定拆,第一件事不是选框架。是画边界。
举个具体的。订单服务和库存服务,谁拥有库存那张表? 如果两边都能写,那恭喜,你给自己埋了一个对账的活,而且这活会跟你三年。
比较稳的做法是按业务能力切,不是按技术分层切。千万别搞成客户服务、数据服务、接口服务这种。那不叫微服务,那叫把单体切成了三片,还得多跨两次网络。
拆完之后你会撞上一个绕不过去的东西:分布式事务。以前一个 begin commit 就完事,现在要 Saga、TCC、本地消息表。绝大多数业务,最终一致性就够了,别一上来追求强一致,那笔账你算不过来。

账要算全
微服务不是免费的。它把编译期的错误,换成了运行期的错误。
以前方法签名对不上,IDE 直接标红。现在接口对不上,半夜三点线上才炸。所以链路追踪、统一日志、告警收敛这些东西,不是可选项,是入场券。没有它们,你就是在裸奔。
还有本地开发。新人入职第一周,为了跑通一个下单流程,本地要起十二个服务、三个中间件,一台 16G 的笔记本直接跪。
这些成本,没人写在 PPT 上。
一个我更愿意推荐的顺序

如果让我重来一遍,我会这么走:
- 先把慢查询、索引、连接池这些基础问题摁死。这一步能解决六七成的性能焦虑,成本也最低。
- 再做读写分离和缓存。注意一致性,别把数据库的锅甩给 Redis。
- 然后考虑模块化单体——代码里严格分模块、禁止跨模块直接查表,但仍然打一个包部署。这一步几乎零成本,却能帮你验证边界画得对不对。
- 边界稳了,某个模块的扩容需求真的和其他模块差出好几个数量级,再把它单独拽出去。
顺序反了,就是花钱买罪受。话糙,但确实是这样。
说句实在的,架构演进不是一场有终点的比赛。它更像搬家——你不会因为换了大房子就把所有东西堆进去,也不会因为东西多就立刻隔出十几个储物间。你得知道每样东西属于哪儿。
最后补一句。任何架构决策,都要写下来:为什么这么选,当时的前提是什么,什么情况下该推翻它。因为两年后接手的人,包括你自己,早忘了。