ELI5 · 说人话
高并发不是「让程序跑得更快」。
是同一时刻涌进来的人,远远超过你这台机器能招呼的数量。
先看清
说「我要做高并发」等于没说。得先说清你要哪个数字、要到多少。
收银台一秒钟能刷几个人。1000 还是 10 万,差着完全不同的架构。
别看平均值。100 个人里最慢那 1 个等了 8 秒,他就走了。
99.9% 意味着一年能挂 8 小时 45 分。多一个 9,成本翻好几倍。
先定这三个数,再选方案。定不下来,后面所有技术选型都是拍脑袋。
找病根
请求要走完整条链才算完。链上每一环能扛的量差着几百倍——最弱的那一环,就是整个系统的上限。
十个系统里九个,第一个垮的都是数据库——它是唯一一个「不能随便复制一份」的东西。所以所有招数,本质上都在做同一件事:别让请求走到数据库。
解法总纲
名词有几百个,招数只有四种。任何花哨方案拆开看,都是这四把刀的组合。
多摆几个收银台
一台不够就上十台,前面站一个负载均衡按人头分。
前提是每台机器身上不存东西——谁接都一样。这叫无状态,是能横向扩的唯一条件。
把答案提前抄下来
同一个问题一秒被问一万遍,没必要查一万次库。
算一次,存内存里,剩下 9999 次直接念。这是最省力、见效最快的一刀。
别让人站着等
下单成功就够了,发短信、加积分、写报表不用当场办完。
丢进消息队列慢慢消化,用户 50 毫秒就走人。顺便还能削掉尖峰。
一张桌子坐不下就分桌
单张表一亿行谁也救不了。按用户 ID 切成 16 份,各查各的。
代价很实在:跨表查询、分页、事务全变难。所以这刀最后再拔。
合起来长这样
高并发架构的真身,就是一层一层的筛子。每一层都拦下一批,让最脆弱的数据库只面对剩下的那一点点。
点一层看看
这就是全部秘密:不是把数据库变强 5 倍,而是让打到它头上的量少 94%。每加一层筛子,系统能接的人就往上翻一个数量级。
会咬人的地方
这些不是「优化」,是不做就一定出事的东西。企业级和玩具的区别全在这一节。
叫缓存雪崩。对策:过期时间加个随机数,别让它们同一秒死;最热的那几个数据干脆不过期,后台悄悄更新;真要重建,只放一个线程进去,其余的等着抄作业。
叫超卖。根因是「先读再写」中间被人插了队。对策:扣减必须是一步原子操作——数据库里用带条件的 UPDATE(库存 > 0 才减),或者 Redis 里用一段 Lua 脚本。绝不能读出来在代码里减完再写回去。
超时重试是常态,重复请求躲不掉。对策:每笔请求带一个唯一编号,服务端认号不认次数,第二次来直接把第一次的结果原样返回。这叫幂等,是所有写接口的及格线。
线程都堵在那儿等它,谁也接不了新活。对策三件套:超时(等 200 毫秒就撒手)、熔断(连续失败就先别打了,过会儿再试)、降级(推荐位加载不出来就显示默认的)。宁可少给一点,不能整个站塌。
对策:任何一个东西都要能被拔掉还活着。数据多副本、机器跨可用区、流量能一键切走。设计的时候就假设「这台机器随时会死」,而不是祈祷它别死。
别一上来就画大图
压用压测把量真打上去,看哪一环先红。是 CPU 满了、连接池空了,还是某条 SQL 走了全表扫描——数字会告诉你,别猜。
改只动那一环。加个缓存能解决的,就不要拆微服务;加两台机器能扛过去的,就不要分库分表。每一刀都有维护成本,拔早了全是债。
再压瓶颈不会消失,只会往后挪一格。原来是数据库,现在可能变成网卡。回到第 1 步,直到扛住你第二节定下的那三个数字为止。
顺带一提:99% 的系统,「加缓存 + 多加几台机器」就够了。分库分表、多机房、单元化那些,是被真实流量逼出来的,不是设计出来的。
高并发不是让每个请求跑得更快,
是让大部分请求根本走不到最后一步。