高并发架构设计是大型网站架构核心,也是大厂重点考察内容,下面我就全面来详解高并发架构设计@mikechen
负载均衡
负载均衡,是将用户请求分散到多台服务器,以减少单台服务器的压力,提高系统的吞吐量、和响应速度。
如下图所示:
可以将 Nginx 配置为负载均衡服务器,然后将请求转发到不同的 Tomcat 实例(比如:Tomcat1、Tomcat2、Tomcat3)。
http { upstream tomcat_cluster { # 定义三个 Tomcat 服务器的 IP 地址和端口 server 192.168.0.101:8080; server 192.168.0.102:8080; server 192.168.0.103:8080; } server { listen 80; server_name example.com; location / { proxy_pass http://tomcat_cluster; # 请求转发到 Tomcat 集群 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } }
当然,除了软件的方式,你也可以使用硬件负载均衡的方式,唯一的缺点就是:贵。
比如:专用硬件负载均衡设备(如: F5、Citrix NetScaler 等),可以配置设备将 HTTP 流量分配到 Tomcat1、Tomcat2、Tomcat3 上。
负载均衡能够有效提高并发请求的处理能力,确保系统在高并发时的稳定性。
分布式架构
为了应对大规模的并发请求,系统通常采用分布式架构,即将应用拆分成多个独立的模块、和服务。
比如:分布式架构里面,最典型的就是:微服务架构。
微服务架构
微服务架构,每个服务可以独立部署、扩展、和管理。
一旦采用微服务架构,就会涉及到:微服务拆分、微服务通信、微服务发现…等等功能。
微服务拆分
将单体应用拆分成多个微服务(如:账户服务、订单服务、库存服务),每个服务负责特定的功能模块。
这种拆分可以避免单个服务成为性能瓶颈,并且易于独立扩展。
微服务间通信
服务之间通过HTTP/REST、gRPC、消息队列等方式进行通信。
当然,你也可以采用消息队列的这种典型的“异步通信”的方式,来提升性能。
一方面,既解耦了服务,另一方面,也提升了吞吐量、和性能。
微服务发现
使用服务注册中心,(如Nacos、Eureka、Consul…等等),来实现服务的自动发现、和负载均衡,避免硬编码服务地址。
通过分布式架构,你可以更容易的扩展性能,但同样也带来了很多技术挑战,比如:分布式事务/分布式一致性…等等技术难题。
数据库优化
在高并发系统中,数据库往往是性能瓶颈,合理的数据库设计、和优化对高并发架构至关重要:
这里,很多数据量大的场景,都会涉及到:分库分表
假设有一个用户表 users
,该表的记录超过亿级,为了减轻单表的读写压力,可以按照用户 ID 对其进行水平拆分。
try (Connection conn = dataSource.getConnection()) { String sql = "INSERT INTO users (user_id, name) VALUES (?, ?)"; try (PreparedStatement ps = conn.prepareStatement(sql)) { ps.setLong(1, 1001L); // user_id 用于分库分表 ps.setString(2, "John"); ps.executeUpdate(); } }
通常需要配合数据库中间件(如 :ShardingSphere、MyCat…等等)来实现,或者自行编写逻辑来处理。
除此之外,你也可以采用垂直拆分。
垂直拆分:是根据业务逻辑将数据库中的不同表,拆分到不同的数据库中,每个库只负责存储一部分业务数据。
假设有三个业务模块:用户管理、订单管理、和库存管理。
初始时所有表都在一个数据库中,随着数据量和并发的增加,可以将这三个模块拆分到不同的数据库。
如下所示:
user_db
:存储用户相关的表,如:users
、user_profiles
等;order_db
:存储订单相关的表,如 :orders
、order_items
等;inventory_db
:存储库存相关的表,如:inventory
、products
等。
NoSQL数据库
在某些场景下,使用NoSQL数据库(如:MongoDB、Cassandra…等等),可以提供更好的扩展性和读写性能。
NoSQL数据库设计初衷,就是为了应对大规模数据处理、和高并发访问,尤其是在读写性能方面具有优势。
比如:MongoDB 使用文档存储模型,数据以JSON-like的BSON格式存储,减少了复杂的表关系、和Join操作。
并且,MongoDB在存储用户生成内容(如:评论、帖子…等)。
// 插入帖子数据 Document post = new Document("title", "MongoDB") .append("content", "MongoDB allows flexible data modeling...") .append("author", new Document("userId", "64eab56f9f7c1a").append("username", "mikechen")) .append("createdAt", new java.util.Date()) .append("likes", 123) .append("comments", List.of( new Document("commentId", "64ea567fc2b1") .append("author", new Document("userId", "64ea67234f7b1").append("username", "mikechen")) .append("content", "Great post! I love MongoDB.") .append("createdAt", new java.util.Date()), new Document("commentId", "64ea8765121b") .append("author", new Document("userId", "64eab1234f7c2").append("username", "alice")) .append("content", "Thanks for sharing!") .append("createdAt", new java.util.Date()) ));
处理大规模社交网络数据时表现出色,因其灵活的数据结构和快速的文档存储和检索能力。
在数据结构相对简单的场景下,读写效率远高于传统关系型数据库。
与关系型数据库相比,NoSQL数据库在数据模型上更为灵活,适用于不定结构、或者动态变化的数据。
并且,NoSQL数据库大多遵循CAP定理,在一致性、可用性和分区容错性之间做出权衡。
许多NoSQL数据库,如:Cassandra,选择牺牲强一致性,以实现更高的可用性和分区容错性。
所以,NoSQL尤其适合在对数据一致性要求不那么严格、需要处理海量数据、以及需要在多个数据中心部署的场景下使用。
分布式缓存
缓存是高并发系统中常用的优化手段,通过缓存热点数据,可以减少对数据库的访问,降低系统响应时间。
比如:Redis 、和 Memcached,是常用的分布式缓存解决方案,广泛用于处理高并发、和跨多个应用实例的场景。
Redis
适用于更多复杂场景,支持多种数据结构和持久化,具有高可用性、和强扩展性;
Memcached
更轻量级,适合简单的键值对缓存,不需要持久化的场景。
可以根据自己的业务场景,你可以选择Redis、或者Memcached,当然,目前用的最多的还是:Redis。
热门商品、首页数据…等,可以放入缓存,缓存可以极大地减少数据库的压力。
例如:可以将首页的商品列表…缓存到 Redis 中,每次首页加载时直接从缓存读取,而不必重复查询数据库。
除此之外,缓存还可以应用到:分布式会话管理、热点数据缓存、排行榜、计数器…等功能。
异步处理
在高并发场景下,某些操作不需要立即完成,适合通过异步处理来解耦、和缓解系统压力。
例如:
例如:在电商平台上进行秒杀活动时,用户同时发起大量购买请求。
通过使用消息队列,可以将所有购买请求写入队列,然后逐一处理库存更新操作,从而避免瞬时大流量压垮数据库。
public class OrderService { private final KafkaTemplate<String, String> kafkaTemplate; @Autowired public OrderService(KafkaTemplate<String, String> kafkaTemplate) { this.kafkaTemplate = kafkaTemplate; } public void placeOrder(Order order) { // 订单处理逻辑 System.out.println("Order placed: " + order.getId()); // 向消息队列发送消息 kafkaTemplate.send("order_topic", order.getId()); } }
消息队列,通过异步处理耗时任务、缓冲流量峰值、解耦系统模块…等手段,极大提升了系统的性能、和扩展性。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》