大家是如何优化高并发下的接口的?
在电商、物流等系统中,订单创建接口往往是核心中的核心。初期用户量少时,直接操作数据库的方案简单有效,但当面对双11、秒杀等高并发场景时,系统可能瞬间崩溃。比如订单的接口,示例代码如下:
@PostMapping("/order/create")
public Order createOrder(OrderDTO orderDTO) {
// 1.参数校验
validateParams(orderDTO);
// 2.生成订单号
String orderNo = generateOrderNo();
// 3.计算金额
calculateAmount(orderDTO);
// 4.同步写数据库
orderMapper.insert(orderDTO);
// 5.返回结果
return orderDTO;
}
针对这种接口,在业务的发展过程中,接口并发越来越大,大家是如何优化这种高并发下的接口的?发布于:1个月前 (03-18) IP属地:
7 个回答
整体优化思路如下:
1、QPS<1000:选择方案1+3
2、1000<qps<5000:选择方案2+4
3、QPS>5000:选择方案2+4+5+分库分表
4、设计多服务,选择方案1+2+3+4+5+6
优化永无止境,但需牢记
1、QPS<1000:选择方案1+3
2、1000<qps<5000:选择方案2+4
3、QPS>5000:选择方案2+4+5+分库分表
4、设计多服务,选择方案1+2+3+4+5+6
优化永无止境,但需牢记
不要过早优化:在需求稳定前优化是浪费
监控先行:Prometheus+Granfana建立监控体系
压测验证:使用JMeter定期全链路压测
发布于:1个月前 (03-18) IP属地:
方案6、分布式事务
伪代码示例如下:
伪代码示例如下:
// Seata AT模式实现
@GlobalTransactional
public void createOrderWithTransaction(OrderDTO dto) {
// 1.扣减库存
stockService.deduct(dto.getItemId());
// 2.创建订单
orderService.create(dto);
// 3.增加积分
pointsService.addPoints(dto.getUserId());
}
发布于:1个月前 (03-18) IP属地:
方案5、服务限流
伪代码示例如下:
伪代码示例如下:
// Sentinel限流配置
@PostResource(name = "createOrder",
blockHandler = "createOrderBlockHandler")
@SentinelResource(value = "createOrder",
blockHandler = "createOrderBlockHandler")
public Order createOrder(...){...}
// 降级处理
public Order createOrderBlockHandler(...) {
throw new BusinessException("系统繁忙,请稍后重试");
}
// 配置QPS阈值
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule("createOrder")
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setCount(5000) // 每秒最大请求数
));
发布于:1个月前 (03-18) IP属地:
方案4:数据库优化
伪代码示例如下:
伪代码示例如下:
-- 创建分表(按用户ID取模)
CREATE TABLE order_2023 (
id BIGINT PRIMARY KEY COMMENT '订单ID',
user_id INT NOT NULL COMMENT '用户ID',
...
) PARTITION BY HASH(user_id % 4);
-- 索引优化
ALTER TABLE orders
ADD INDEX idx_user_status (user_id, status);
配置建议连接池调优(Druid配置maxActive=100)
启用批量插入(MyBatis的foreach批量插入)
发布于:1个月前 (03-18) IP属地:
方案3:缓存预热
适用场景:商品库存校验、用户信息查询
伪代码示例如下:
适用场景:商品库存校验、用户信息查询
伪代码示例如下:
// Redis预存库存信息
public boolean checkStock(String itemId) {
String key = "stock:" + itemId;
Long stock = redisTemplate.opsForValue().decrement(key);
if(stock < 0){
redisTemplate.increment(key); // 回滚
throw new BusinessException("库存不足");
}
return true;
}
// 定时同步数据库
@Scheduled(cron = "0 0/5 * * * ?")
public void syncStockToDB() {
// 批量更新数据库库存
}
注意:需处理缓存与DB的一致性发布于:1个月前 (03-18) IP属地:
方案2:消息队列削峰
流程图如下:
流程图如下:
客户端 -> API网关 -> 消息队列(RabbitMQ/Kafka) -> 订单服务 -> DB
伪代码示例如下:
// RabbitMQ生产者
@PostMapping("/order/create")
public String createOrder(OrderDTO dto) {
String msgId = sendToMQ(dto);
return "订单已进入排队,ID:"+msgId;
}
// RabbitMQ消费者
@RabbitListener(queues = "order.create.queue")
public void processOrder(OrderDTO dto) {
orderService.realCreateOrder(dto);
}
实测数据峰值承载能力提升10倍
需配合死信队列做消息重试
发布于:1个月前 (03-18) IP属地:
方案1、异步处理-拆分主链路
原理:将非核心逻辑异步化,通过线程池解耦
伪代码示例如下:
缺点:需要处理异步任务失败补偿
原理:将非核心逻辑异步化,通过线程池解耦
伪代码示例如下:
// 使用@Async异步注解
@Async("orderAsyncExecutor")
public void asyncProcess(Order order) {
// 1.发送短信通知
smsService.sendOrderCreatedMsg(order);
// 2.更新统计信息
statisticsService.updateDailySales();
}
// 配置线程池
@Bean("orderAsyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("Order-Async-");
return executor;
}
优点:响应时间从500ms降到50ms缺点:需要处理异步任务失败补偿
发布于:1个月前 (03-18) IP属地:
我来回答
您需要 登录 后回答此问题!