一、高并发系统的核心设计原则
1. 无状态化设计:水平扩展的基石
无状态服务通过剥离会话状态实现请求的任意节点处理,是分布式系统横向扩展的前提。以电商订单系统为例,用户请求需携带Token或SessionID,服务节点通过Redis集群验证身份,而非本地内存存储。这种设计使得新增节点无需同步状态,配合负载均衡器(如Nginx的轮询策略)可实现线性扩容。
代码示例:基于JWT的无状态认证
// 服务端生成Tokenpublic String generateToken(User user) {return Jwts.builder().setSubject(user.getId()).setExpiration(new Date(System.currentTimeMillis() + 86400000)).signWith(SignatureAlgorithm.HS512, "secretKey").compact();}// 任意节点验证Token@GetMapping("/api/data")public ResponseEntity<?> getData(@RequestHeader("Authorization") String token) {Claims claims = Jwts.parser().setSigningKey("secretKey").parseClaimsJws(token.replace("Bearer ", "")).getBody();// 处理业务逻辑}
2. 异步非阻塞架构:提升吞吐量的关键
同步调用在高并发下易引发线程阻塞,异步化通过事件驱动或消息队列解耦上下游。以订单支付场景为例,用户发起支付后,系统立即返回受理结果,实际扣款通过RocketMQ异步处理:
// 支付服务异步处理@RocketMQMessageListener(topic = "PAYMENT_TOPIC", consumerGroup = "PAYMENT_GROUP")public class PaymentConsumer implements RocketMQListener<PaymentEvent> {@Overridepublic void onMessage(PaymentEvent event) {// 调用第三方支付接口boolean success = thirdPartyPay(event.getOrderId(), event.getAmount());// 更新订单状态orderService.updateStatus(event.getOrderId(), success ? "PAID" : "FAILED");}}
此种模式使单节点QPS从同步的200+提升至异步的2000+,同时通过消息重试机制保障可靠性。
3. 多级缓存体系:降低数据库压力
缓存是应对读多写少场景的利器,需构建本地缓存(Caffeine)+分布式缓存(Redis)+静态资源CDN的三级架构。以商品详情页为例:
- 本地缓存:缓存基础信息(价格、库存),TTL设为5秒
- Redis缓存:存储完整商品数据,采用Cache-Aside模式
- CDN缓存:静态图片、CSS文件通过Nginx配置缓存头
Cache-Aside模式实现
public Product getProduct(Long productId) {// 1. 查本地缓存Product product = localCache.get(productId);if (product != null) return product;// 2. 查RedisString redisValue = redisTemplate.opsForValue().get("product:" + productId);if (redisValue != null) {product = JSON.parseObject(redisValue, Product.class);localCache.put(productId, product);return product;}// 3. 查DB并更新缓存product = productDao.selectById(productId);if (product != null) {redisTemplate.opsForValue().set("product:" + productId, JSON.toJSONString(product), 1, TimeUnit.HOURS);localCache.put(productId, product);}return product;}
二、高并发场景下的数据层优化
1. 数据库分库分表策略
当单表数据量超过500万时,需按业务维度拆分。以用户表为例,可采用用户ID哈希取模分库:
-- 分库SQL示例SELECT * FROM user_${userId % 4} WHERE user_id = ?;
ShardingSphere-JDBC等中间件可透明化分片逻辑,但需注意跨库JOIN问题,建议通过冗余字段或异步数据同步解决。
2. 读写分离与连接池调优
主从架构下,写请求路由至主库,读请求分散至从库。Druid连接池配置示例:
@Beanpublic DataSource dataSource() {DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setUrl("jdbc:mysql://master:3306/db");druidDataSource.setInitialSize(10);druidDataSource.setMaxActive(100);druidDataSource.setTestWhileIdle(true);return druidDataSource;}
通过spring.datasource.druid.read.url配置从库地址,结合AbstractRoutingDataSource实现动态数据源切换。
三、业务层的高并发设计模式
1. 限流与降级策略
Sentinel框架提供流量控制能力,以接口维度限流为例:
@GetMapping("/api/resource")@SentinelResource(value = "getResource", blockHandler = "handleBlock")public String getResource() {// 业务逻辑return "success";}public String handleBlock(BlockException ex) {return "系统繁忙,请稍后再试";}
配置规则:每秒1000个请求,超出后触发熔断,返回降级结果。
2. 队列削峰填谷
秒杀场景下,通过Redis预减库存+消息队列异步下单:
// 阶段1:Redis预减库存Long stock = redisTemplate.opsForValue().decrement("seckill:stock:" + productId);if (stock < 0) {throw new RuntimeException("库存不足");}// 阶段2:消息队列异步处理seckillMessage.setProductId(productId);seckillMessage.setUserId(userId);rocketMQTemplate.sendOneWay("SECKILL_TOPIC", seckillMessage);
此种设计将瞬时高峰流量转化为持久化消息,避免数据库直接承压。
四、监控与持续优化
1. 全链路监控体系
构建Prometheus+Grafana监控看板,关键指标包括:
- 接口响应时间(P99/P95)
- 错误率(5XX比例)
- 线程池活跃数
- 缓存命中率
2. 压测与容量规划
使用JMeter进行全链路压测,逐步增加并发用户数,观察系统瓶颈点。典型优化路径:
- CPU瓶颈 → 优化算法复杂度
- 内存瓶颈 → 减少对象创建,使用对象池
- 网络瓶颈 → 启用HTTP/2,压缩传输数据
五、典型场景解决方案
1. 实时日志分析系统
采用Flink+Kafka架构:
- 日志采集端:Filebeat收集应用日志
- 消息队列:Kafka分区数与消费者线程数匹配
- 流处理:Flink窗口聚合计算PV/UV
- 存储:ClickHouse列式存储支持快速查询
2. 分布式ID生成器
雪花算法(Snowflake)实现:
public class SnowflakeIdGenerator {private final long datacenterId;private final long machineId;private long sequence = 0L;private long lastTimestamp = -1L;public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException("Clock moved backwards");}if (lastTimestamp == timestamp) {sequence = (sequence + 1) & 0xFFF;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;return ((timestamp - 1288834974657L) << 22) |(datacenterId << 17) |(machineId << 12) |sequence;}}
结语
高并发系统设计是架构、代码、运维的综合体现,需遵循”先抗住再优化”的原则。从无状态服务、异步架构到多级缓存,每个环节都需精细设计。实际开发中,建议通过混沌工程(Chaos Engineering)验证系统韧性,持续迭代优化方案。