高并发系统设计:从理论到实践——一个被创业公司“优化”过的前端眼中的后端世界
作者:老K,前XX科技前端工程师(已倒闭),现居武汉光谷软件园某不知名工位,日均咖啡摄入量3杯,房租3500/月。
去年十月的一个周五晚上,我还在公司加班改一个“明天上线”的首页动效。办公室里只剩我和后端小李。他盯着屏幕上疯狂刷屏的日志,嘴里念叨着:“完了完了,QPS又爆了……Redis崩了,MySQL在哭……”
我当时心里还嘀咕:你们后端不是天天吹什么高并发、分布式、微服务吗?怎么连个秒杀活动都扛不住?
结果三天后,老板在全员会上轻描淡写地说:“公司现金流紧张,大家先回家休息几天。”
再后来,HR微信发来一句:“很遗憾,公司决定停止运营。”
我收拾电脑那天,看着空荡荡的工位,突然意识到:我们根本没搞懂什么是高并发,就敢接百万级用户量的项目。
一、你以为的高并发 vs 我们干的高并发
在那家公司之前,我对“高并发”的理解停留在B站视频和掘金文章里——“用Redis缓存热点数据”、“消息队列削峰填谷”、“Nginx负载均衡”……听起来牛得不行。
但现实是啥?
- 秒杀活动前一周,产品经理拍脑袋说:“我们要支持10万人同时抢购!”
- 后端团队一共3个人,其中2个刚毕业,1个是我这种前端被迫看Java代码的“伪全栈”。
- 服务器?阿里云最低配ECS一台,数据库是RDS共享型,内存4G。
- 监控工具?
top+tail -f日志,外加一个简陋的 Grafana 面板(还是我搭的,因为没人会)。
更离谱的是,我们居然真的上了线。
活动当天,凌晨0点刚过,系统直接502。用户骂声刷爆客服群。技术群里,CTO在吼:“赶紧扩容!加机器!”
可我们的代码压根没做无状态设计,数据库连接池硬编码在配置文件里,Redis key 还是用 user_id 直接拼字符串……这不是高并发,这是高风险行为艺术。
二、Java:爱恨交织的“祖传语言”
作为前端,我原本对Java敬而远之。但在那家公司,后端全是Spring Boot,我被迫读Java代码、调接口、甚至帮他们写单元测试(别问,问就是“前端也要懂业务”)。
说实话,Java生态在高并发场景下的工具链确实成熟,但前提是你会用。
工具对比:别让“能跑就行”害了你
| 场景 | 我们当初的做法 | 正确姿势(事后诸葛亮) |
|---|---|---|
| 缓存 | 直接 @Cacheable 注解,key 乱写,没设TTL |
Redis + 分布式锁 + 热点Key探测(比如阿里Tair) |
| 限流 | 没有限流,全靠祈祷 | Sentinel / Hystrix + 动态规则配置 |
| 异步 | 手写 new Thread() 起线程 |
RocketMQ / Kafka + 消费者组重试机制 |
| 数据库 | 单表500万行,没分库分表,慢查询堆成山 | ShardingSphere + 读写分离 + 冗余字段冗余 |
| 监控 | 日志grep + 人工盯屏 | Prometheus + AlertManager + ELK |
最讽刺的是,我们连连接池参数都没调过。HikariCP默认最大连接数10,而高峰期请求轻松破千。结果就是:所有请求排队等DB连接,最后超时炸掉。
后来我面试新工作时,被问到:“你们怎么处理数据库瓶颈?”
我苦笑:“我们当时以为重启就能解决一切。”
三、工具不是万能的,但没有工具是万万不能的
很多人觉得“高并发=堆中间件”,其实大错特错。工具只是放大器,你的设计才是核心。
举个真实例子:我们有个“领取优惠券”接口,逻辑是:
- 查用户是否领过
- 插入领取记录
- 扣减库存
看起来没问题?但在高并发下,第1步和第2步之间有窗口期,导致同一用户领多次,库存负数。
我们当时的“解决方案”是:加 synchronized 锁方法。
结果呢?单机锁在集群环境下无效,而且吞吐量直接腰斩。
正确的做法应该是:
- 库存扣减用数据库行锁(
SELECT ... FOR UPDATE) - 或者用 Redis 的
INCR+ Lua 脚本原子操作 - 再或者,干脆把“领券”变成异步消息,由消费者幂等处理
工具在这里的角色是什么?
- Redis 提供原子操作能力
- RocketMQ 保证消息至少一次投递
- Arthas 帮你在线诊断锁竞争
但如果你连“并发安全”这个概念都没有,给再多工具也是白搭。
四、武汉光谷的深夜:前端也能懂高并发?
很多人觉得高并发是后端的事,前端只要切好图、写好组件就行。
但经历了那次崩溃,我彻底改观了。
前端其实是高并发的第一道防线。
比如:
- 用户疯狂点击“提交订单”,你前端不做防重,后端就得扛住重复请求
- 列表页无限滚动不加节流,API QPS 直接翻倍
- 图片不懒加载,带宽先被打爆
在那家公司倒闭前一个月,我偷偷在前端加了:
- 按钮点击后自动 disabled + 3秒冷却
- 所有GET请求加本地缓存(哪怕只有5秒)
- 关键接口失败自动重试(带退避策略)
效果?虽然救不了大局,但至少把50%的无效请求挡在了门外。
后来我去面试,跟新公司的架构师聊起这事,他说:“很多后端抱怨前端不懂性能,其实你们能做的比想象中多。”
五、从“能跑就行”到“稳如老狗”:我的认知升级
公司倒闭后,我花了三个月时间系统补课。不是为了跳槽涨薪(虽然最后月薪从15k涨到了22k),而是不想再经历那种无力感。
我做了三件事:
亲手搭一套高并发Demo
用 Spring Boot + Redis + RabbitMQ + Nginx,模拟秒杀。故意制造各种故障:Redis宕机、MQ堆积、DB慢查询……然后看系统怎么崩,再一步步加固。死磕工具链
学会用 JMeter 压测,用 Arthas 看线程堆栈,用 SkyWalking 追踪链路。工具不会让你变强,但能让你看清问题在哪。理解“取舍”
高并发不是追求极致性能,而是在成本、复杂度、稳定性之间找平衡。
比如:99%的业务根本不需要分库分表,做好缓存+限流就够了。
六、给正在踩坑的你:几点真心话
别迷信“大厂方案”
阿里双11的架构,放到你5人小团队就是灾难。先解决眼前最痛的点:是数据库慢?缓存击穿?还是网络带宽?压测不是上线前才做的事
我们当初连基本的压力测试都没做,就敢上生产。现在我司每周五下午固定压测,哪怕只是模拟100并发。前端请多关心后端
不是要你去写Java,但至少知道:一个接口背后可能涉及多少服务、多少DB查询。沟通时少说“这个很简单”,多问“这个对你们压力大吗?”工具要学,但别当工具人
会用Sentinel不代表你懂限流算法,会搭Kafka不代表你理解消息可靠性。知其然,更要知其所以然。
结语:在光谷软件园继续搬砖
现在的公司不大,但技术氛围务实。上周我们刚上线了一个新活动,QPS峰值8000,系统稳如老狗。
庆功宴上,后端同事敬我:“多亏你前端加了防抖,省了我们好多事。”
我笑了笑,心里却想起那个崩溃的夜晚——如果当初我们多一点敬畏,少一点侥幸,或许结局会不同。
高并发系统设计,从来不是炫技,而是对用户负责,对系统负责,对自己负责。
武汉的冬天很冷,光谷软件园的写字楼灯火通明。
但这一次,我不焦虑了。
因为我知道:真正的高并发,不在PPT里,在每一行谨慎的代码里,在每一次认真的压测里,在每一个愿意为稳定性多花五分钟的人心里。
共勉。

评论 0