晚上8点,报警群炸了。
"接口超时!""服务挂了!""页面打不开!"
打开监控面板,核心数据库CPU飙到100%,所有SQL都在排队。不是服务宕机,是数据库扛不住了。
新活动上线5分钟,大量用户涌入排行榜页面。每次请求都要全表扫描千万级数据——慢查询把数据库CPU占满,所有打到这个库的操作全部超时。
- 加从库? 来不及。搭建主从、配置同步、改代码读写分离,至少两小时,流量已经打过来了。
- 重构? 时间不够。SQL优化、索引调整、压测发布,周期太长,线上等不起。
- 限流? 可以。但活动刚上线就限流,用户体验断裂,转化率直接归零,业务侧不会买单。
最终决策:动态降级。关闭排行榜实时刷新,保留基础参与入口,将慢查询强制熔断。3分钟后,数据库CPU与核心接口RT回落至正常范围,服务恢复。
但这只是止血。
这不是代码Bug,是架构设计缺陷:高消耗查询与核心业务共用了同一个数据库实例。
后续改进: 添加缓存层、优化慢查询,并在连接池配置查询超时,超时自动断开,释放连接,防止慢SQL拖垮整个实例。
根本方案: 把非核心业务的高消耗查询拆到独立的数据库实例,与核心业务物理隔离。从此,活动流量峰值不再波及核心链路。
这些决策不在代码里,而在架构层的判断:哪些功能可以牺牲,哪些必须保护;哪些资源可以共享,哪些必须隔离。
AI能帮忙写代码,但它做不了这些判断。
AI能做什么,不能做什么
先承认一个事实:AI写代码比我快。
让它写个排序算法、补全单元测试、生成代码模板——几秒钟搞定。质量还不错,比我手写的规范。
但有些事AI做不了:
理解业务上下文。 某个字段叫balance,是余额还是积分?AI不知道,除非你把整个数据模型、业务规则、历史演进全喂给它。但这些东西往往散落在文档、代码注释、老员工的脑子里——连你自己都不一定说得清。
做取舍决策。 性能优化10%,但会增加复杂度。做不做?AI会给你两个方案,但不会告诉你选哪个——因为它不知道你的团队规模、维护成本承受能力、未来演进方向。
跨系统思考。 你改了一个接口,影响的是上游调用方、下游依赖、监控系统、报警阈值、数据报表……AI看不到这些,它只能看到你给它看的代码。
把握技术演进节奏。 现在引入新技术栈,会不会和半年后的架构规划冲突?这个决策需要时间维度,AI没有。
所以,问题不是"AI会不会取代程序员",而是"AI会让哪种程序员被淘汰"。
答案很明确:只会写代码、不会做架构决策的程序员。
架构师不是title,是思维方式
很多人觉得"架构师"是个职位——干了10年技术,升到架构师,年薪翻倍。
这是误解。
架构师不是职位,是一种能力:在技术、业务、团队、时间四个维度上做权衡,并为决策后果负责的能力。
让我用一个真实场景解释。
场景:支付系统的幂等性设计
某社交App的支付模块,用户消费后调用钱包服务扣减余额。最直接的代码:
func Deduct(ctx context.Context, userID int64, amount decimal.Decimal) error {
_, err := db.ExecContext(ctx, `
UPDATE wallet_balance
SET balance = balance - ?
WHERE user_id = ? AND balance >= ?
`, amount, userID, amount)
return err
}
这段代码虽然解决了并发问题(原子操作,不会少扣),但面临网络超时重试,用户可能被多扣钱。
AI通常会建议:"加个唯一ID,用数据库唯一索引做幂等。"
但问题是:唯一ID从哪来?存哪里?冲突了怎么告警?
这些决策,AI给不出唯一答案。让我带你推演一线战场的常见方案:
方案A:业务流水号 + Redis分布式锁
func DeductWithLock(ctx context.Context, req *DeductRequest) error {
// 用业务类型和业务流水号加锁
lockKey := fmt.Sprintf("deduct_lock:%s:%s", req.BizType, req.BizNo)
ok, err := redis.SetNX(ctx, lockKey, "1", 30*time.Second).Result()
if err != nil || !ok {
return errors.New("请勿重复提交")
}
defer redis.Del(ctx, lockKey)
// 扣款
if err := db.DeductBalance(ctx, req.UserID, req.Amount); err != nil {
return err
}
return nil
}
问题: Redis挂了怎么办?锁30秒到期了,但业务扣款还在执行怎么办?
方案B:流水表 + 唯一索引幂等
func Deduct(ctx context.Context, req *DeductRequest) error {
// 创建资金流水(用业务类型+业务流水号建唯一索引,防止重复创建)
err := db.CreateFlow(ctx, req.BizType, req.BizNo, req.UserID, req.Amount)
if err != nil {
if db.IsDuplicateKeyError(err) {
return nil // 已处理过,幂等返回成功
}
return err
}
// 扣款
if err := db.DeductBalance(ctx, req.UserID, req.Amount); err != nil {
return err
}
return nil
}
问题: 资金流水创建了,扣款失败了,怎么办?
方案C:本地事务保障(单库场景)
func DeductWithTransaction(ctx context.Context, req *DeductRequest) error {
return db.Transaction(ctx, func(tx *sql.Tx) error {
// 创建流水
err := tx.CreateFlow(ctx, req.BizType, req.BizNo, req.UserID, req.Amount)
if err != nil {
if tx.IsDuplicateKeyError(err) {
return nil
}
return err
}
// 扣款
if err := tx.DeductBalance(ctx, req.UserID, req.Amount); err != nil {
return err
}
return nil
})
}
此方案成立的前提是 资金流水表 与 钱包余额表 位于同一个数据库实例。若已拆分至不同库,需升级为本地消息表+MQ最终一致性方案,这在专栏后续文章会详细展开。
问题: 事务持有数据库连接时间长,高并发下可能成为瓶颈。
最终选了方案C。 理由如下:
- 业务约束:重复扣款用户会投诉,扣款失败财务对不上账,一致性要求极高。方案B无事务,可能有流水但未实际扣款,不满足要求。扣款接口QPS不高,事务持有连接的时间可控,瓶颈风险可以接受。
- 技术约束:事务保证原子性,数据一致性好。Redis方案多了一个故障点。
- 团队约束:团队对数据库事务有实战经验,对ACID语义理解到位。Redis分布式锁的边界情况(进程崩溃、时钟漂移)反而更容易踩坑,运维成本更高。
这个判断,AI做不了。 因为它不知道我们的基础设施架构(主从分离)、团队能力栈(数据库强、Redis运维弱)、以及业务对一致性的容忍度(零容忍)。
架构师的价值就在这里:把技术约束、业务目标、团队能力放在一起,做出一个当前最优的选择。
成为架构师的三个关键能力
1. 看清系统全貌
不是看一个服务,是看整个系统。
下面是某社交APP用户在聊天室内发一条消息的调用链路:
graph TD
Client[用户端: 发送消息请求] --> C1
subgraph SG_Core [核心业务层: ChatRoom 服务]
C1[消息组装与基础校验]
C2[调用关系服务: 获取粉丝/好友列表]
C3[调用礼物服务: 暴击概率计算]
C4[调用音视频服务: 连麦状态同步]
C5[......]
C6[调用 IM 服务: 触发下发流程]
end
C1 --> C2 --> C3 --> C4 --> C5 --> C6
subgraph SG_Push [消息推送层: IM 网关与路由分发]
G1[消息网关: 风控审核 & 敏感词过滤]
G2[内容安全: AI 模型识别 & 权限校验]
G3[审核通过: 写入消息队列]
MQ[(Kafka / RocketMQ 消息队列)]
R1[消息消费: 按类型路由分发]
R2[单播推送: 按用户 ID 路由至对应节点]
R3[广播推送: 全量下发 / 支持平台/版本/VIP 过滤]
R4[优先级队列: 高优系统通知插队处理]
P1[长连接网关: WebSocket 实时推送]
P2[离线兜底: APNs / FCM 系统级推送]
end
C6 --> G1 --> G2 --> G3 --> MQ --> R1
R1 --> R2
R1 --> R3
R1 --> R4
R2 --> P1
R3 --> P1
R4 --> P1
P1 --> P2
subgraph SG_Async [异步处理层: 数据闭环与业务衍生]
A1[消息队列异步消费]
A2[更新推荐系统用户特征]
A3[触发广告归因回调]
A4[实时数仓同步]
end
C6 -. 异步埋点触发 .-> A1
A1 --> A2
A1 --> A3
A1 --> A4
classDef user fill:#f8fafc,stroke:#64748b,stroke-width:2px,rx:6px;
classDef core fill:#eff6ff,stroke:#3b82f6,stroke-width:2px,rx:6px;
classDef push fill:#f5f3ff,stroke:#8b5cf6,stroke-width:2px,rx:6px;
classDef async fill:#f0fdf4,stroke:#22c55e,stroke-width:2px,rx:6px;
class Client user;
class C1,C2,C3,C4,C5,C6 core;
class G1,G2,G3,MQ,R1,R2,R3,R4,P1,P2 push;
class A1,A2,A3,A4 async;
这个图不是文档里写的,是从代码、日志、监控、事故复盘里一点点拼出来的。
怎么练这个能力?
- 第一周:选一个核心服务,画出它3层以内的上下游依赖。来源:代码里的HTTP/gRPC调用、消息队列订阅关系、数据库表的主外键。
- 第二周:选一个完整功能(比如"用户充值"),从入口到底层存储,画出完整调用链路。标出每个环节的超时时间、失败处理、数据一致性级别。
- 验证指标:你能不查代码,向同事描述这个服务的上下游依赖关系,且对方没有异议。
2. 理解业务逻辑
技术是为业务服务的。不理解业务,技术决策就是瞎猜。
产品说做一个"开宝箱"功能。技术上看,逻辑很简单:
func OpenBox(ctx context.Context, userID int64) (*BoxReward, error) {
// 扣宝箱钥匙
if err := db.DeductKey(ctx, userID, 1); err != nil {
return nil, err
}
// 随机出奖
reward := RandomReward()
// 发奖
return reward, SendReward(ctx, userID, reward)
}
三行逻辑,上线就行了吧?
但业务上,这个"随机"背后全是坑:
- 运营说1%出稀有奖。1%是每箱独立计算,还是累计100箱保底?保底要不要做重置周期?概率引擎不是
rand() < 0.01这么简单。 - 用户充值买了钥匙,开箱得奖后送人。然后申请退款——奖品已经流转出去了,退不退?退的话钱从哪出?
- 活动最后一分钟,10万用户扎堆开箱。并发高的时候出奖率会不会异常?要不要加锁?失败要不要排队重试?
- 上线后运营问:这周稀有奖的实际出奖率是多少?你能回答吗?理论概率1%,但实际出了多少、哪些用户拿到了、有没有异常集中——没有监控就是黑盒,出了问题也说不清楚。
- 运营每周改奖池和概率。热更新时正在开箱的用户怎么处理?加不加版本控制?需不需要灰度?用户拿旧配置的截图来投诉"我开箱的时候明明是这个概率",你怎么排查?
这些问题,AI不会问你。但如果你不想清楚,上线后一定会出事。
怎么练这个能力?
写完代码后问自己5个问题:
- 业务规则边界:概率是独立还是保底?有没有每日/全服限量?限量是硬限制还是软限制?
- 异常和回滚:扣了钥匙但出奖失败怎么办?充值买的宝箱退款时奖品怎么回收?事务边界在哪?
- 高并发边界:活动结束前扎堆开箱,要不要加锁?失败了要不要排队重试?
- 可观测性:实际出奖率是多少?有没有异常集中?出了问题能不能说清楚当时发生了什么?
- 配置变更追溯:运营改了概率,用户拿旧配置截图来投诉,你能不能证明当时用的是哪套配置?
对照产品文档或找产品经理对一遍。你会发现你漏了多少东西。
3. 掌控技术演进节奏
不是追新技术,是在合适的时间引入合适的技术。
关键是:什么时候是"合适的时间"?
某社交App早期用PHP。团队3个人,DAU不到10万。PHP开发快,部署简单,够用。
后来DAU涨到50万。高峰期PHP-FPM进程数打满,请求排队,响应时间从200ms飙到2秒。
这时候该不该切Go?
3个月前不切——DAU只有30万,PHP还能扛,切Go要占用2个核心开发,业务迭代会停。
3个月后再切——DAU可能到80万,那时候不是"切不切"的问题,是"系统能不能活"的问题。
现在切,是因为业务压力已经到了临界点,团队规模也刚够支撑两条线(业务迭代+重构)。
早做,浪费资源。晚做,风险失控。
最终用的方案:绞杀者模式——不是一次性重写,而是按接口逐步迁移。
# Nginx配置:按路径切流量
location /api/v1/chat/ {
proxy_pass http://go-service; # 新服务
}
location /api/v1/ {
proxy_pass http://php-service; # 旧服务兜底
}
流程:Go实现新接口 → Nginx切10%流量 → 观察1周(错误率/RT) → 稳定切50% → 继续切 → PHP下线。
一年半后,PHP服务全部下线。整个过程用户无感知。
这个方案不是从书上抄的,是根据**团队规模(6人,能分出2人做重构)、业务压力(DAU 50万,PHP快扛不住)、风险承受能力(零容忍数据丢失,不能一次性切)**做出来的。
节奏感,就是知道什么时候必须动手,什么时候可以再等等。
怎么练这个能力?
现在去做一件事:观察你系统里的技术债务,列一个优先级清单:
1. [P0] 某服务单点 → 3个月内必须解决(流量预计涨50%,单点扛不住)
2. [P1] 某表没有索引 → 等DAU破X万再优化(现在量还小)
3. [P2] 日志没结构化 → 有空就做(不影响主流程)
每一条后面写上**判断依据:**为什么是P0?为什么是现在?
三个月后回看:P0解决了吗?当时判断的流量涨50%对不对?你的依据准不准?
这个复盘,才是真正积累节奏感的方式。
AI是验证者,架构师是决策者
先想清楚,再让AI干活。 这句话听起来是废话。但实际操作中,90%的人用AI的顺序是反的:拿到需求,先让AI写代码,边写边改,边改边问——最后代码写了一堆,架构一塌糊涂。
AI在架构阶段的价值是逼问假设,不是生成代码。
怎么用AI逼问自己?
有一个固定句式:"这个方案,在XXX情况下会怎样?"
我:支付幂等方案(事务+唯一索引),在极端情况下会怎样?
AI:
- 数据库主从延迟时,从库查不到刚创建的订单,可能重复扣款
- 事务超时没返回,客户端重试,会报"订单已存在"但不知道扣没扣钱
...
虽然它说的不一定对,但能帮忙发现一些没考虑到的边界情况。
AI最大的价值:把你脑子里的假设逼问出来。
你以为自己考虑了并发,AI问你"主从延迟呢"。
你以为自己考虑了幂等,AI问你"事务超时没返回呢"。
每一个追问,都是架构决策的深度。AI不会替你做判断,但它能帮你把判断的依据逼出来。
核心要点
-
AI会取代只会写代码的程序员,不会取代能做架构决策的程序员。
-
架构师不是title,是思维方式:在技术、业务、团队、时间四个维度做权衡,并为结果负责。
-
三个关键能力:
- 看清系统全貌(画调用链路图,第一周一个服务,第二周一条链路)
- 理解业务逻辑(写5个业务约束条件,对照产品文档验证)
- 掌控技术演进节奏(列技术债务优先级清单,三个月后复盘判断对不对)
-
AI是验证者,架构师是决策者。 用AI逼自己把假设说清楚,用AI发现设计漏洞,但最终判断永远是你自己做。
写在最后
我见过很多程序员,技术很强,但只会执行需求。产品说什么做什么,从不问"为什么"。
也见过一些程序员,技术一般,但能看清系统全貌,吃透业务逻辑,在关键时刻做正确决策。
后者,才是AI时代不可替代的人。
从今天开始,别只盯着代码。跟着我一起,抬起头,看看整个系统。那才是你的战场。
📖 下篇预告:《这个需求该怎么实现?》
我们会聊:从一个模糊的业务需求,如何推导出清晰的实现路径。不是讲道理,是给模板。读完你就能照着做。