@Akintola_steve: https://x.com/Akintola_steve/status/2055620856802357587
摘要
一份实用的蓝图,用于设计能够处理100万并发用户的后端系统,涵盖架构决策如语言选择、负载均衡、数据库分片、多层缓存及弹性模式。
查看缓存全文
缓存时间: 2026/05/17 03:28
如何设计一个能支撑100万用户而不崩溃的后端系统
一份面向后端工程师的2026年实用架构蓝图
构建一个为1000用户服务的系统很容易。但构建一个在100万并发用户下仍保持快速、廉价且坚如磐石的系统,却是大多数工程师失败的地方。
本文为你提供一份完整且经实战检验的蓝图。没有空话。只有真正关乎扩展性的架构决策、权衡和模式。
1. 首先明确你的需求
这是大多数工程师跳过的步骤,也是他们六个月后不得不重构一切的原因。
在写任何代码之前,先确定你的非功能性需求:
-
峰值QPS: 每秒1万到5万次请求
-
P99延迟: 低于200毫秒(目标低于100毫秒)
-
可用性: 99.99%,即每月最多约4分钟停机时间
-
一致性模型: 金融数据强一致性,动态消息和时间线最终一致性
-
成本上限: 提前设定每1000用户的严格美元成本上限
使用扩展立方体从三个维度思考:
-
X轴: 水平复制。运行更多相同的服务器。
-
Y轴: 功能分解。拆分为更小、更专注的服务。
-
Z轴: 数据分区。按用户ID或区域分片。
仅凭这一思维模型即可避免90%的扩展灾难。
2. 选择正确的基础设施
语言与框架:
-
Go或Rust:追求原始性能和内存效率
-
TypeScript(NestJS)或Java/Kotlin(Spring Boot):当团队交付速度比原始吞吐量更重要时
API策略:
-
面向公众:REST + GraphQL
-
内部服务间通信:gRPC。类型安全、快速、支持流式传输。
从一个模块化单体应用开始。只有当某个特定服务成为可衡量的、被证实的瓶颈时,才将其拆分为微服务。
过早微服务是扩展性下工程效率的最大杀手。
3. 负载均衡与边缘层
全球用户意味着全球延迟,除非你将基础设施推到边缘。
请求路径如下:
-
用户(拉各斯 / 伦敦 / 孟买)
-
Cloudflare或Fastly:CDN、DDoS防护、边缘缓存
-
全球负载均衡器:AWS Global Accelerator或GCP等效产品
-
API网关:限流、WAF、机器人检测
-
应用服务
在100万用户规模下,边缘层是你的第一道防线。在请求到达应用服务器之前,尽可能多地处理流量。
4. 应用层设计
四条不可妥协的规则:
每个服务必须无状态。 会话存储在Redis或Dragonfly中,绝不在应用内存中。如果服务器宕机,用户会话不会随之丢失。
后台任务应放入队列。 在此规模下使用Kafka或Pulsar。不是RabbitMQ。不是内存处理。不是setTimeout。
在调用级别构建弹性。 断路器、带抖动的重试以及每个出站调用的硬超时。一个慢依赖不应级联成整个系统故障。
基于正确信号进行自动扩展。 CPU是滞后指标。应根据队列深度和错误率进行扩展。这些指标在CPU数字变化之前就能反映真实的系统压力。
5. 数据库策略
单个数据库既是性能天花板,也是单点故障。永远不要只用一个。
推荐技术栈:
-
主要OLTP:PostgreSQL + Citus实现水平分片
-
高写入路径:Cassandra或ScyllaDB
-
缓存与实时数据:Redis集群
-
分析与聚合:ClickHouse
所有写操作都通过查询路由器(Vitess或Citus)路由。按user_id使用取模策略进行分片,确保数据均匀分布。只读副本放在PgBouncer后面进行连接池管理。
一条再怎么强调也不为过的规则:在第一天就选择你的分片键。 上线后再更改分片键是一个团队能经历的最痛苦的迁移之一。
6. 多层缓存
缓存是高扩展性系统中最大的成本杠杆。目标缓存命中率高于85%。
-
第1层,边缘CDN缓存: 静态资源和可公开缓存的响应永远不会到达源站。
-
第2层,应用层Redis缓存: 计算结果、会话数据和热门记录存放在这里。
-
第3层,查询结果缓存: 昂贵的数据库读取在查询层面被缓存。
只有完全缓存未命中时,请求才会到达数据库。
关于失效策略:通过Kafka进行事件驱动失效。用户资料更新事件应立即使相关的缓存键失效。仅靠TTL对关键数据并不可靠。
7. 可观测性
你无法调试你看不到的东西。在此规模下,你需要从第一天就开始全面的可观测性,而不是等到凌晨2点生产环境出问题之后。
技术栈:
-
Prometheus:指标
-
Jaeger:分布式追踪
-
Loki:日志
-
全部通过OpenTelemetry进行仪表化,全部流入Grafana仪表盘
-
Alertmanager将关键告警路由到PagerDuty
四个黄金信号。在每个服务上进行仪表化:
-
延迟:请求耗时
-
流量:请求量
-
错误:失败请求的比率
-
饱和度:资源接近极限的程度
定义真正的SLO。跟踪你的错误预算。在用户注意到之前发出告警。
8. 数据一致性与幂等性
分布式系统会以部分、不可预测的方式失败。从一开始就为此设计。
发件箱模式。 在与业务逻辑相同的事务中,将事件写入数据库表。后台进程读取并发布这些事件。即使消息代理宕机,事件也不会丢失。
Saga模式。 对于跨多个服务的事务,使用一系列补偿操作代替两阶段提交。如果下游步骤失败,每个步骤都有定义的回滚。
幂等键。 每个变更操作应接受一个唯一的请求ID。如果相同的请求到达两次,返回原始结果。这是在不可靠网络上处理重试的唯一安全方式。
在此规模下,最终一致性不是弱点。而是正确的架构权衡。
9. 安全
-
所有内部服务之间使用mTLS。每个服务间调用都经过认证和加密。
-
零信任网络。没有服务默认信任另一个服务,无论请求来自何处。
-
传输中和静态数据都加密,无一例外。
-
定期进行混沌工程。在生产环境中故意杀死随机Pod,以在流量帮你发现之前验证你的弹性假设。
在受控测试中发现故障模式,远比在凌晨2点流量高峰时才发现要好得多。
10. 完整架构
将所有部分整合在一起:
-
100万用户
-
边缘 + CDN + WAF
-
全球负载均衡器
-
API网关(限流 + 认证)
-
无状态应用服务
-
Redis集群 / Kafka事件总线 / 分片PostgreSQL + Cassandra
-
后台工作节点
-
可观测性层:Prometheus、Grafana、Jaeger、Loki
此架构可承载100万日活用户,并有充足的余量扩展到数千万用户,而无需根本性重写。
开始之前
-
从小做起并测量一切。基于数据而非假设进行优化。
-
在任何发布之前,使用k6或Locust以预期峰值流量的2倍进行负载测试。
-
使用功能标志和金丝雀部署。永远不要直接将功能推送给100%的用户。
-
在优化之前先分析热点路径。瓶颈很少在你认为的地方。
-
对非关键工作负载使用竞价/抢占式实例,以大幅削减基础设施成本。
延伸阅读: 《数据密集型应用系统设计》(Martin Kleppmann) | Uber工程博客 | Netflix技术博客 | ByteByteGo
本文中的每个模式目前都在生产系统中运行。
能够承受扩展的系统与在压力下崩溃的系统之间的区别不是天赋。而是在流量到来之前尽早做出的架构决策。
收藏本文。需要时再回来查阅。
你想扩展哪个部分?在回复中告诉我。
#后端工程 #系统设计 #分布式系统 #软件工程
相似文章
@techyoutbe: https://x.com/techyoutbe/status/2076189458869928324
一份关于 40 个后端概念的指南,分为六个阶段,从 HTTP 基础到系统架构,旨在帮助工程师准备系统设计面试。
ByteByteGoHq/system-design-101
一个GitHub仓库,提供复杂系统设计概念的视觉化和简单解释,涵盖API、负载均衡、HTTP和网络等主题。
@ghumare64: 这是你今天可能读到的最简洁的架构设计之一。将独立的工作单元组合在一起时,它们…
一种用于构建智能代理后端的架构方法,该方法使用独立的工作单元,这些单元可以在没有集成代码的情况下组合在一起,并运行在一个共享引擎上,该引擎提供队列、状态、发布订阅、可观测性、HTTP、沙箱和定时任务功能。
@0xlelouch_: 我依然会推荐给在职开发者的十大系统设计资源:1) 《设计数据密集型应用》(Kleppmann)——重新…
一条推特线程,列出了十大系统设计资源,包括书籍、博客和框架,并附有Martin Fowler网站的链接以供进一步阅读。
@jhleath: https://x.com/jhleath/status/2065408690992148698
作者解释了如何构建一个能够在恒定时间内每秒启动数百万个沙箱的计算平台,重点介绍了使用Cassandra和S3进行解耦调度和能力聚合。