好的,处理高并发和高可用的问题是后端架构设计的核心挑战,也是衡量架构师能力的关键指标。两者相辅相成,但又各有侧重。
下面我将它们拆开,再结合起来讲解如何系统性地处理。
---
### 高并发 (High Concurrency)
高并发的核心在于:**系统如何高效地处理大量同时到来的请求**。目标是提高**吞吐量(Throughput)** 和降低**延迟(Latency)**。
#### 核心思路:分而治之,层层缓冲
1. 流量层:卸载与分发
* 负载均衡 (Load Balancing):这是高并发架构的**入口和基石**。所有流量都应先经过负载均衡器再到达后端服务。
* 硬件:F5, A10(性能强,成本高)。
* 软件:Nginx (HTTP/HTTPS层,第7层)、LVS (网络层,第4层)、HAProxy。
* 策略:轮询、加权轮询、最少连接数、IP哈希等。
* DNS轮询:在更上层通过DNS将域名解析到多个IP地址,实现初步的流量分发,通常用于异地多机房。
2. 应用层:异步化与水平扩展
* 无状态服务 (Stateless Service):这是**水平扩展的前提**。服务实例本身不保存用户会话(Session)等状态信息。所有状态都存储到外部的集中式存储(如Redis、数据库)中。这样,任何请求都可以被任何实例处理,扩缩容变得非常简单。
* 池化技术 (Pooling):使用数据库连接池、HTTP连接池等,避免频繁创建和销毁连接的开销,复用连接,极大提升性能。
* 异步处理 (Asynchronous Processing):
* 线程模型:使用多线程、事件驱动(如NIO)模型处理请求,避免阻塞。例如,Netty框架。
* 业务解耦:对于耗时操作(如发送邮件、生成报表、处理视频),不要阻塞主请求流程。采用**消息队列(MQ)**,将请求异步化。用户请求立刻返回,后台工作进程从MQ中消费消息并慢慢处理。这实现了**削峰填谷**,将流量高峰稀释成一段时间内的平稳流量。
* 示例:Kafka, RabbitMQ, RocketMQ。
3. 数据层:缓存与分库分表
* 缓存 (Caching):这是应对高并发读操作的**银弹**。
* 缓存策略:
* Cache-Aside (旁路缓存):最常用。应用先读缓存,命中则返回;未命中则读数据库,写入缓存后再返回。
* Read/Write Through:缓存代理所有读写操作。
* 缓存位置:
* 客户端缓存:浏览器、APP。
* CDN缓存:静态资源(图片、视频、HTML/CSS/JS)。
* 反向代理缓存:Nginx缓存页面片段。
* 分布式缓存:**Redis**、Memcached,集群化部署以承载大量请求。
* 缓存问题:必须处理**缓存穿透**、**缓存击穿**、**缓存雪崩**。
* 数据库优化:
* 读写分离:主库负责写,多个从库负责读,通过binlog同步。显著提升读能力。
* 分库分表 (Sharding):当单表数据量巨大时,将数据分散到多个数据库或表中。分为**水平分片**(按行,如按用户ID哈希)和**垂直分片**(按列,将不常用字段拆分出去)。常用中间件:ShardingSphere, MyCat。
* 数据库选型:在合适场景使用NoSQL。例如,海量日志、埋点数据用时序数据库(InfluxDB);社交关系用图数据库(Neo4j)。
---
### 高可用 (High Availability)
高可用的核心在于:**系统如何保证持续可用的服务时间,避免单点故障(SPOF)**。目标是提高**SLA(Service Level Agreement)**,如达到99.99%(年停机时间约52分钟)或99.999%(年停机时间约5分钟)。
#### 核心思路:冗余 + 自动故障转移
1. 冗余 (Redundancy) - 消除单点故障
* 多实例部署:任何核心服务、数据库、缓存、中间件都不能是单点的,必须至少以集群方式部署。
* 多机房部署 (Multi-Zone/Region):在同城或异地建立多个数据中心,防止因机房断电、网络光缆被挖断等导致服务完全不可用。
2. 故障转移 (Failover) - 快速发现与切换
* 健康检查 (Health Check):负载均衡器或服务注册中心(如Nacos, Consul, Eureka)会定期向服务实例发送心跳包,检查其是否存活。
* 自动切换:当健康检查失败,判断某个实例不可用时,自动将其从服务列表中剔除,并将流量路由到其他健康的实例。这个过程对用户应无感知。
3. 数据可靠性 - 冗余的基石
* 数据备份:定期对数据库进行全量和增量备份,并最好在异地保存一份。
* 数据复制:
* 主从复制 (Master-Slave Replication):如MySQL主从,数据从主库异步/半同步复制到从库。从库可读,主库宕机后可提升一个从库为主库。
* 多主复制 (Multi-Master Replication):如Galera Cluster for MySQL。
* 分布式共识算法:使用Raft、Paxos等算法的分布式数据库/配置中心,能自动处理主节点选举和数据一致性,如Etcd, Consul。
4. 容错与自愈 (Resilience & Self-Healing)
* 服务熔断 (Circuit Breaker):当调用某个服务频繁失败时,熔断器会打开,后续调用直接快速失败,不再发起真实调用。保护系统不被拖垮。例如Hystrix, Sentinel, Resilience4j。
* 服务降级 (Degradation):在系统压力过大时,暂时关闭一些非核心功能(如推荐、积分),释放资源保证核心流程(如下单、支付)可用。
* 限流 (Rate Limiting):控制单位时间内处理的请求数量,防止系统被突发流量冲垮。常用算法:计数器、漏桶、令牌桶。可在网关(如Spring Cloud Gateway)层面实现。
* 弹性伸缩 (Auto Scaling):在云平台上,根据CPU、内存、QPS等指标,自动增加或减少服务实例数量,以应对流量波动。
---
### 高并发 + 高可用:综合架构示例
一个典型的应对高并发和高可用的后端架构可能如下所示(微服务模式):
1. 用户请求首先到达 DNS,解析到**负载均衡器 SLB**(软件或硬件)。
2. SLB 将流量分发给**API网关集群**。网关负责限流、鉴权、路由。
3. API网关将请求路由到后端的**微服务集群**(如用户服务、订单服务、商品服务)。
4. 所有微服务都是无状态的,并注册到**服务注册与发现中心**(如Nacos)。服务间通过RPC或HTTP调用,客户端负载均衡器(如Ribbon)会从注册中心获取健康实例列表进行调用。
5. 服务间调用时,使用**熔断降级组件**(如Sentinel)防止雪崩。
6. 对于**读请求**,服务优先查询**Redis分布式缓存集群**。
7. 对于**写请求**,服务操作**MySQL数据库集群**(主从架构,读写分离)。如果数据量巨大,已进行分库分表。
8. 对于耗时操作,服务将消息发送到**Kafka/RocketMQ消息队列集群**,由后台Worker异步消费,实现削峰填谷。
9. 所有组件的**日志**被收集到**ELK**,**指标**被**Prometheus**采集并由**Grafana**展示,**调用链**由**SkyWalking/Jaeger**追踪,形成完整的可观测性体系。
总结一下关键心法:
* 高并发靠**缓存、异步、分片**。
* 高可用靠**冗余、自动故障转移、熔断降级**。
* 两者共同的基础是:**负载均衡**、**无状态服务**、**全面的监控告警**。
最终,所有的技术方案都是权衡(Trade-off)的结果,需要在**性能、一致性、可用性、成本**和**开发复杂度**之间做出最适合当前业务阶段的选择。