java如何编写一个支持百万并发的订单接口呢?
编写大并发接口,是所有开发人员都梦寐以求的场景,但是又有几人能接触到这种场景呢?
下文笔者将一一道来,如下所示:
下文笔者将一一道来,如下所示:
编写大并发接口,其实不是靠语言本身, 而是靠优秀的架构和中间件及一些优化 ================================================ 下文笔者将从以下几个方面讲述百万并发接口的使用示例 整体架构设计 → 核心模块拆解 → 技术实现要点 → 性能调优策略
🧱一、整体架构设计(分布式+高并发)
要支撑百万并发,必须采用 分布式微服务架构 并引入各种中间件来提升吞吐量和稳定性例
[用户请求]
↓
[Nginx / LVS 负载均衡]
↓
[API 网关(鉴权、限流、路由)]
↓
[订单服务集群(Spring Cloud 微服务)]
↓
[缓存层(Redis / Caffeine)]
↓
[数据库集群(MySQL 分库分表)]
↓
[异步队列(Kafka / RocketMQ)]
二、核心模块与关键技术点
✅ 1. 接口设计(幂等性、防重提交)
@PostMapping("/createOrder")
public ResponseEntity<?> createOrder(
@RequestHeader("X-Request-ID") String requestId,
@RequestBody OrderRequest request) {
if (redisTemplate.hasKey("order:" + requestId)) {
return ResponseEntity.ok("请勿重复提交");
}
// 创建订单逻辑
String orderId = orderService.createOrder(request);
// 缓存请求ID防止重复提交
redisTemplate.opsForValue().set("order:" + requestId, orderId, 5, TimeUnit.MINUTES);
return ResponseEntity.ok(orderId);
}
⚠️ 使用 Redis 或本地缓存记录 [requestId]避免重复下单
✅ 2. 订单号生成(唯一、有序、可追踪)
推荐使用 **雪花算法(Snowflake)** 或 **美团 Leaf**:
public class SnowflakeIdGenerator {
private final long nodeId;
private long lastTimestamp = -1L;
private long lastId = 0L;
public SnowflakeIdGenerator(long nodeId) {
this.nodeId = nodeId << 12;
}
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException("时钟回拨");
}
if (timestamp == lastTimestamp) {
lastId++;
long maxSequence = ~(-1L << 12);
if (lastId > maxSequence) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
lastId = 0;
}
lastTimestamp = timestamp;
return (timestamp << 22) | nodeId | lastId;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
}
✅ 3. 数据库存储(分库分表 + 读写分离)
- 使用 **ShardingSphere / MyCat / TDDL** 实现分库分表
- 使用 **MyBatis Plus / JPA / 自定义 DAO 层**
- 示例配置(ShardingSphere):
```yaml
spring:
shardingsphere:
datasource:
names: ds0,ds1
ds0:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ds0
username: root
password: root
ds1:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ds1
username: root
password: root
rules:
sharding:
tables:
orders:
actual-data-nodes: ds$->{0..1}.orders_$->{0..1}
table-strategy:
standard:
sharding-column: user_id
sharding-algorithm-name: order-table-inline
key-generator:
column: order_id
type: SNOWFLAKE
4.缓存穿透、击穿、雪崩处理
| 场景 | 解决方案 |
| 缓存穿透 | 布隆过滤器(Bloom Filter) |
| 缓存击穿 | 互斥锁、逻辑过期时间 |
| 缓存雪崩 | 设置不同过期时间、集群部署 |
//Redis 缓存示例
public Order getOrder(String orderId) {
String cacheKey = "order:" + orderId;
Order order = redisTemplate.opsForValue().get(cacheKey);
if (order == null) {
synchronized (this) {
order = redisTemplate.opsForValue().get(cacheKey);
if (order == null) {
order = orderMapper.selectById(orderId); // DB 查询
redisTemplate.opsForValue().set(cacheKey, order, 5 + new Random().nextInt(60), TimeUnit.SECONDS);
}
}
}
return order;
}
5.异步落盘(削峰填谷)
-使用 **Kafka / RocketMQ / RabbitMQ** 将下单操作异步化
-例:发送订单创建消息到 MQ
kafkaTemplate.send("order-topic", JSON.toJSONString(order));
消费者端:
@Kafkalistener(topics = "order-topic")
public void consume(String message) {
Order order = JSON.parseObject(message, Order.class);
orderService.saveToDatabase(order);
}
6.限流熔断(保障系统稳定性)
-使用Sentinel/Hystrix/Resilience4j
@GetMapping("/createOrder")
@SentinelResource(value = "createOrder", fallback = "fallbackCreateOrder")
public ResponseEntity<?> createOrder(...) {
.
}
public ResponseEntity<?> fallbackCreateOrder(...) {
return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body("当前人数过多,请稍后再试");
}
常见性能调优建议
| 类别 | 建议 |
| JVM 调优 | 合理设置堆大小、GC回收器(如G1)、JVM 参数 |
| 数据库优化 | 索引优化、慢查询分析、连接池配置(HikariCP) |
| 线程池配置 | 自定义线程池,避免阻塞主线程 |
| 系统监控 | 使用Prometheus+Grafana+SkyWalking监控性能指标 |
| 压力测试 | 使用JMeter/Gatling 进行压测,找出瓶颈点 |
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


