|
去年双十一,大型某头部电商平台峰值QPS冲到80万,网站服务器集群却只扩了15%。建设秘密不在代码,大型在架构——他们把90%的网站静态资源请求挡在了CDN边缘节点,真正打到源站的建设动态请求不到8%。这个数字说明一件事:大型网站的大型核心不是“扛住流量”,而是网站“让流量根本到不了核心”。 先聊分层。建设见过太多团队把Web层、大型应用层、网站数据层塞进同一台机器,建设初期跑得挺欢,大型日活过万就开始半夜告警。网站合理的建设做法是物理隔离:接入层只跑Nginx和LVS,负责SSL卸载和四层转发;应用层拆成无状态容器,随便扩缩容;数据层再按业务垂直切分,订单库和用户库不在同一个MySQL实例里。有个做在线教育的朋友,2022年把直播转码和课程管理从同一集群拆开,故障率直接降了六成。拆分的代价是运维复杂度上升,但比起数据库被转码任务拖死的风险,这点成本不值一提。 缓存策略得说透。Redis做热点数据缓存是标配,但很多人忽略本地缓存。Caffeine或者Guava Cache放在应用层,能挡掉30%以上的Redis查询。某社交平台把用户会话信息同时写入本地堆外内存和Redis,Redis集群的QPS从12万降到4万。还有个坑:缓存穿透。布隆过滤器加空值缓存能解决大部分问题,但更狠的是在接入层做参数校验——非法ID直接返回400,根本不进应用层。 数据库这块,分库分表不是万能药。见过一个日订单50万的系统,硬拆成64个分片,结果跨分片查询把中间件拖垮。后来改成订单主表按用户ID哈希分32片,订单详情表用订单号做一致性哈希,关联查询走异步任务补偿,系统才稳下来。读写分离也有讲究:主库写,从库读,但主从延迟超过200ms时,强制走主库。这个阈值怎么定?看业务容忍度。支付回调延迟200ms可能没事,库存扣减延迟200ms就是超卖。 消息队列选型别跟风。Kafka吞吐高,但延迟不稳定,适合日志和离线分析;RocketMQ事务消息靠谱,电商订单场景更合适;RabbitMQ延迟低,但堆积能力差,金融交易用得多。有个做物联网的团队,设备上报数据用Kafka,指令下发用RabbitMQ,各取所长。队列积压时,先看消费端是不是卡在某个慢查询上,别急着加消费者——有时候加消费者反而让数据库更慢。 最后说容灾。同城双活听着高级,但跨机房延迟摆在那,数据库同步至少5ms起步。更实际的做法是“同城灾备+异地只读”:主机房故障,灾备机房30秒内接管;异地机房只提供查询服务,写请求切回主机房。某在线旅游平台2023年机房断电,灾备切换用了47秒,用户几乎无感知。代价是灾备机房常年跑着50%的冗余资源,这笔钱省不得。 架构没有标准答案。日活百万和日活千万的系统,设计思路完全不同。别照搬大厂方案,先算清楚自己的峰值QPS、数据量和延迟容忍度,再决定用几层、缓存放哪、数据库怎么拆。技术选型是权衡,不是信仰。 |