从单机架构到负载均衡的互联网架构全流程

全篇为:从单机架构到负载均衡的互联网架构演进。

从单机架构(程序与数据库部署在同一服务器)开始,指出随着用户增长,会出现资源竞争。

解决方案是将应用与数据库拆分到不同服务器。当单台应用服务器无法承受流量时,引入负载均衡服务器(如 Nginx)将请求平均分发给多台应用服务器,实现水平扩展。

初期单机架构如下图,流量比较小,此时把应用程序与数据库都部署到同一台服务器上。

随着用户量上升,应用程序和数据库开始争夺 CPU、I/O 和内存资源,CPU 和内存被两边抢来抢去,导致整体卡顿。物理分开应用服务器和数据库服务器是分布式架构的初期阶段。

如何解决这一问题?

把它们拆开(物理分离)。分成应用服务器和数据库服务器。

应用服务器:专职处理 HTTP 请求、执行业务逻辑(比如计算价格、校验权限)。

数据库服务器:专职负责磁盘 I/O(读写数据)、执行 SQL 查询。


从单台应用服务器扩展到应用集群

Q&A

为什么要集群?

单台服务器性能有物理上限(CPU、内存、网络带宽);当每秒请求数(QPS)超过单机承载极限时,只能"加机器"------这就是横向扩展(Scale Out)
集群解决了什么问题?

高可用:一台机器宕机,其他机器还能继续服务,不会全站瘫痪。

高并发:5 台机器一起扛流量,总处理能力翻 5 倍(理想情况)。


没有负载均衡器时,虽然有多台服务器,但用户不知道访问哪台,只能靠 DNS 轮询(粗糙且无法屏蔽故障)。

如何解决呢?在所有应用服务器前面架设了一个负载均衡器(Load Balancer,例如 Nginx、HAProxy 或云上的 SLB)

其中负载均衡有两个主要作用:

流量分发:确保每台应用服务器收到的请求数量大致相等。这样,加机器(即水平扩展)才能真正转化为处理能力的线性提升。

故障自愈 :它会持续检查后面的应用服务器是否存活。如果某台服务器宕机,负载均衡器会立即将其踢出集群,不再分发请求。用户完全感知不到后端有机器坏了------这就是高可用。

那数据库慢了,怎么办?------用空间(内存)换时间(速度)

应用集群能扛住海量请求,但所有请求最终都要去查数据库。数据库的数据在磁盘上,磁盘 I/O 是机械运动,速度比内存慢千倍以上 。既然数据库慢是因为要读磁盘,那就在应用和数据库之间加一道"内存墙"(缓存)。绝大多数读请求直接从内存返回,根本不用经过数据库。

但是又出现了新问题:缓冲区容量有限,无法容纳全部的数据。所以要采用多级缓存方式

部署到 Redis 上:当前查询所需时间从 ms 级降低到 ns 级。


引入 Redis 缓存,挡住了 80% 的读请求,但又遇到了新的问题:写入操作(增、删、改) 以及缓存未命中的读取 ,依然要穿透到数据库。随着业务量增大,数据库的磁盘 I/O 和锁冲突会越来越严重。那么针对写操作慢和锁竞争问题,对应的解决方案是:读写分离(主从复制),主库负责写,从库负责读,通过数据同步保持一致性。

为解决单表数据量过大(如超 1000 万行)的问题,需要进行分库分表。垂直分库按业务领域(如用户、商品、订单)拆分;水平分表则将一张大表按一致性哈希算法拆成多张小表,配合数据库中间件使用。


垂直分库:

在这张图之前,虽然有主从库,但用户表、商品表、订单表全都挤在同一个物理数据库里)。

痛点 :所有业务的数据挤在一起,某个业务(比如订单)突发大查询,会拖垮整个数据库的CPU和I/O,导致用户登录(查用户表)都变慢。一个业务生病,全家跟着吃药。

解法 :按业务领域(用户、商品、订单)将数据库拆分成独立的数据库实例。每个数据库都有自己的专属主库和从库。

效果资源隔离;独立扩展


引入CDN、反向代理与搜索引擎(Elasticsearch/MongoDB)

支持几十万并发的其他架构组件:CDN用于将静态资源缓存到离用户最近的节点;

反向代理(Nginx)用于隐藏真实服务器、抵御攻击。同时,为应对模糊查询、全文检索等需求,需引入搜索引擎(如Elasticsearch)和NoSQL数据库(如MongoDB)以支持非结构化数据。


但是将所有代码集中在一个巨型工程(巨石应用)会导致维护困难。

解决方案:按业务边界拆分成独立的子系统(如用户、订单、商品集群),形成分布式架构。

进一步地,为追求极致灵活性,可按单一职责将子系统继续拆分为更细的微服务(如登录、会员、支付服务),每个微服务可独立开发、部署和扩容。


以前(单体/分层架构):所有代码(用户、商品、订单)打包在一个大工程里。改一行订单代码,整个项目要重新编译、测试、部署。

现在(微服务拆分) :每个业务(用户、商品、订单)是一个独立的项目、独立的进程、独立部署。每个服务拥有自己独立的数据库(对应你之前做的垂直分库)。

拆分微服务后,用户服务要查订单数据,就不能直接调方法了(因为不在同一个进程里)。跨系统调用可通过RPC实现。RPC(如 Dubbo/gRPC):性能更高,像调本地方法一样调远程服务(二进制传输,序列化更快)。

以前用 Nginx 做负载均衡,IP 是写死在配置文件里的。但在微服务中,服务实例随时会变(扩容、缩容、宕机重启),IP 是动态变化的。

为管理大量服务,需要服务注册与发现中心(如Zookeeper)和消息队列(如Kafka)来实现异步通信、系统解耦和削峰填谷。微服务架构还需引入全链路追踪、限流熔断降级等机制。

为简化部署,使用Docker将应用与环境一起打包,并用Kubernetes(k8s)管理Docker容器。

最后,进行总结:

阶段 核心动作 解决什么问题(学术化表述)
1. 单机 应用+数据库在一起 快速验证与低成本启动:最小化初期基础设施投入,降低部署复杂度,缩短产品上市周期。
2. 分离 应用和数据库拆分 消除资源竞用与提升隔离性:通过物理/逻辑隔离,避免应用逻辑与数据存储争抢CPU、内存及I/O资源,保障系统整体吞吐量与稳定性。
3. 应用集群 加多台应用 + Nginx 引入负载均衡与水平扩展机制:通过横向扩容分摊请求压力,突破单机处理上限,同时实现故障自动剔除,提升系统可用性(HA)。
4. 缓存 引入 Redis 构建多级缓存体系,降低数据库读压力:利用内存介质的高速读写特性,将热点数据前置缓存,显著降低数据库I/O频次与响应延迟(RT)。
5. 读写分离 主从复制 实现读写流量隔离与锁竞争消解:通过主从复制架构,将查询请求分流至从库,消除读写操作间的锁争用,提升数据库并行处理能力。
6. 垂直分库 按业务拆库(用户/商品/订单) 面向领域的数据物理隔离与故障隔离:按业务边界拆分数据存储,避免跨业务资源争抢,实现故障域的隔离,并为后续服务化拆分奠定数据基础。
7. 水平分表 数据散落到多张表 突破单表数据量上限,缓解索引层级退化:通过分片策略将数据打散至多张物理表,降低B+树索引深度,保障数据写入与查询的线性扩展能力。
8. 多引擎 引入 ES、MongoDB 多模数据存储与专业化查询引擎适配:针对全文检索、半结构化数据、多维分析等场景引入专用存储引擎,弥补传统关系型数据库在非结构化场景下的能力短板。
9. 微服务 拆应用 + RPC + MQ + K8s 实现组织架构与技术架构的对齐(康威定律):通过服务化拆分降低系统耦合度,引入异步通信与容器编排实现弹性伸缩与故障自愈,支撑大规模协同开发与持续交付(CI/CD)。

写入与查询的线性扩展能力。 8. 多引擎 引入 ES、MongoDB 多模数据存储与专业化查询引擎适配 :针对全文检索、半结构化数据、多维分析等场景引入专用存储引擎,弥补传统关系型数据库在非结构化场景下的能力短板。 9. 微服务 拆应用 + RPC + MQ + K8s 实现组织架构与技术架构的对齐(康威定律):通过服务化拆分降低系统耦合度,引入异步通信与容器编排实现弹性伸缩与故障自愈,支撑大规模协同开发与持续交付(CI/CD)。

相关推荐
SelectDB1 小时前
快手 AB 场景提速 145 倍,从 Spark 到 Apache Doris 的加速实践
数据库·spark·开源
SelectDB1 小时前
阶跃星辰 Agent 可观测实践:为什么 Trace 数据底座选择 SelectDB?
大数据·数据库·agent
冷静的楼房1 小时前
使用ThreadPool发起同步的调用
数据库
一个天蝎座 白勺 程序猿1 小时前
自动SQL优化实战|吃透调优接口+报告配置+统计+索引全流程落地
数据库·sql·sql优化
TDengine (老段)1 小时前
# TDengine TMQ 最佳实践 — 可靠消费、容错与监控
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
杨云龙UP2 小时前
Windows SQL Server 备份无法传输至异地共享目录排查处理
运维·服务器·数据库·windows·共享·smb·异地备份传输
落寞的电源2 小时前
Delegate = Object + MethodInfo
开发语言·数据库·c#
Thomas.Chan2 小时前
数据中心动环监控系统架构详解
运维·网络·计算机网络·其他·系统架构·数据中心
要开心吖ZSH3 小时前
处方物流信息同步优化:从 36 秒到亚秒级的踩坑记录
java·数据库·mysql·性能优化