🔥 一、为什么你的系统看起来没问题,但一上高峰就卡?
我参与过无数线上事故,发现一个共同点:
所有大型系统的危机点都来自“资源抢夺”。
- 线程抢锁
- 线程抢 CPU
- 队列抢容量
- 请求抢 Redis
- 写入抢 DB 锁
- 消费者抢同一个热点分区
- 服务抢线程池执行权
- GC 抢 CPU 时间片
只要资源可被竞争,就一定会出现极端情况。
🧨 二、资源争抢的三个本质规律(非常重要)
规律 1:资源不是耗尽,而是“被抢光”
很多开发看到 CPU 100% 时觉得是“CPU 不够”。
其实往往是某个任务独占了 CPU。
例子:
- 大对象序列化
- JSON 解析
- 批量 SQL 拼装
- 正则表达式
这些都会把 CPU 拉满,让其它请求无法执行。
规律 2:队列不是安全线,而是“等待死亡”
队列长度代表什么?
不是缓冲,而是排队模型。
排队 = RT 增加 = 超时 = 重试 → 再次排队 → 形成死循环。
队列积压是很多系统雪崩的起点。
规律 3:锁争用比你想象的严重得多
比如你写了一个简单的库存扣减:
UPDATE product SET stock = stock - 1 WHERE id = 123;
当 2000 人同时抢一本书时,会发生什么?
- 全部请求在 DB 层排队
- 只有一个线程能执行
- RT 直接进入秒级
- 线程池沾满
- 服务不可用
这不是代码问题,是资源争用问题。
🔍 三、深度拆解:资源争用发生在哪些地方?
以下是行业真实热点:
1)线程池争用(最常见)
- 核心线程不够
- 阻塞任务太多
- 队列太长
- 拒绝策略不合理
结果:
全链路阻塞
2)数据库争用
- 锁等待
- 事务冲突
- 全表扫描顶满 IOPS
- 热点主键冲突
结果:
订单无法提交、库存扣减失败、审批卡死
3)Redis 热 key 争用
- 所有请求打到一个 key
- Redis 单线程被打爆
- RT 飙升
这属于微观热点。
4)MQ 分区争用
- 单分区不能并行消费
- 导致消息堆积
- 最终整个链路拉跨
5)应用锁争用
比如:
synchronized (userId) {
// 业务逻辑
}
在高并发下会直接演变为:
“全员排队”问题
🛠 四、如何从根源解决资源争夺?
下面给出工程实践路径。
🧩 1. 隔离(Isolation)
通过隔离减少争用:
- 线程池隔离
- 租户隔离
- 分区隔离
- 分库分表
- 热 key 分散
隔离是最有效的手段。
🔥 2. 限流(Limit)
把不合理的流量挡在外面。
🚦 3. 排队削峰
- 消息队列
- 本地缓冲
- 异步执行
削峰填谷。
🪢 4. 分散(Sharding)
- 分散请求
- 分散 key
- 分散数据
- 分散写入点
🧮 5. 降级(Degrade)
在资源耗尽前主动牺牲次要能力。
🧼 6. 重试要节制(Avoid Retry Storm)
大量系统因为自动重试造成“二次灾难”。
💡 五、真实案例:库存扣减的资源争夺战
某电商系统库存扣减量大,突然一致失败。
原因:
- 所有库存写请求集中到一个商品记录
- DB 锁争用严重
- RT 爆炸
- 线程池占满
- 服务雪崩
最终改为:
- 乐观锁
- 分片库存(比如 10 个库存桶)
- 异步扣减
- 热点隔离
系统恢复性能。
🎬 六、结语:资源争夺不可避免,但可被治理
系统能不能扛住压力,不取决于机器,而取决于:
- 限流策略
- 隔离策略
- 分散策略
- 降级策略
- 异步策略
- 架构前瞻性
资源争夺是一切性能问题的底层逻辑。