专业的编程技术博客社区

网站首页 > 博客文章 正文

扩展到百万用户规模:真希望早点知道的架构设计

baijin 2025-05-26 13:37:38 博客文章 5 ℃ 0 评论

刚上线时,能有100个日活用户我们就很满足了。但短短几个月内,用户数就突破了一万,接着是十万。而系统扩展问题的堆积速度比用户增长还要快。

我们的目标是100万用户,但支撑千级用户的架构很快就捉襟见肘。回望这段历程,这是我当初就该搭建的架构——以及在高压扩容中获得的经验教训。

第一阶段:行之有效的巨石(直到它失效)

我们的第一个技术栈很简单:

该配置轻松应对了500名并发用户。但在5,000名并发用户时:

监控显示存在数据库锁、垃圾回收暂停和线程争用问题。

第二阶段:投入更多服务器(但忽略了真正的瓶颈)

我们在NGINX后面添加了更多应用服务器:

读取扩展性良好,但写入仍集中于单一MySQL实例。

负载测试下:

瓶颈不在于CPU——而在于数据库。

第三阶段:引入缓存

我们为读取密集型查询添加了Redis作为缓存层:

这使得数据库负载降低了60%,缓存读取的响应时间缩短至200毫秒以下。

1000个并发用户资料请求的基准测试:

第四阶段:打破单体架构

我们将核心功能拆分为微服务:

每个都有其自己的数据库模式(最初为同一数据库实例)。

服务间通信采用REST API:

但链式REST调用导致了延迟膨胀。一个请求会扩散成3到4个内部请求。

大规模实施时,这会严重拖累性能。

第五阶段:消息传递与异步处理

我们为异步工作流添加了Kafka:

使用Kafka后,注册延迟从1.2秒降至300毫秒,因为高成本的下游任务实现了异步处理。

第六阶段:扩展数据库

当用户数达到50万时,我们的MySQL实例就撑不住了——即使启用了缓存。

我们添加了:

读取副本 → 读写分离
分片 → 基于用户的分区(用户0-99.9万、100万-200万等)
归档表 → 将冷数据移出热路径

示例查询路由器:

这减少了跨分片的写入争用和查询时间。

第7阶段:可观测性

用户超过10万时,缺乏可见性的调试简直是一场噩梦。

我们添加了:

分布式追踪(Jaeger + OpenTelemetry)
集中式日志(ELK技术栈)
Prometheus + Grafana仪表盘

示例Grafana指标:

在引入可观测性之前,诊断延迟激增需要数小时。之后,只需几分钟。

第八阶段:CDN与边缘缓存

在100万用户时,40%的流量访问了静态文件(图片、头像、JS包)。

我们将它们迁移到了Cloudflare CDN并启用了激进缓存:

这卸载了源服务器70%的流量。

最终架构 我会尽快构建

如果能重来,我会跳过阶段直接早点打造这个:

关键经验:

缓存不是可选项
数据库扩展需尽早设计
异步处理至关重要
可观测性越早投入越有价值

扩展不仅仅是“增加更多服务器”——而是要在每一层消除瓶颈。

最终基准测试(100万用户,每秒1000次请求):

结束语

扩展到百万用户不在于炫技,而在于按正确顺序解决关键问题。

最初服务1000名用户时的架构,将无法支撑百万级的规模。

在遭遇失败模式之前,先做好应对计划。

在规模扩张中,哪个架构错误让你付出了最大代价?我很想听听。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表