大家是如何优化高并发下的接口的?

提问者:帅平 问题分类:微服务
在电商、物流等系统中,订单创建接口往往是核心中的核心。初期用户量少时,直接操作数据库的方案简单有效,但当面对双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;
}
针对这种接口,在业务的发展过程中,接口并发越来越大,大家是如何优化这种高并发下的接口的?
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
优化永无止境,但需牢记
不要过早优化:在需求稳定前优化是浪费
监控先行: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属地:
我来回答