【MapSheep】
[好记性不如烂笔头]

一、先搞懂:电商高并发的核心场景

高并发主要集中在3个核心环节:

  1. 秒杀/促销(瞬间海量请求,比如618开抢);
  2. 商品详情页(大量用户同时浏览);
  3. 订单/支付(高并发创建订单、扣库存)。

二、核心解决方案(极简+实战)

1. 缓存兜底(最基础、性价比最高)

核心思路:把高频访问的数据(商品详情、库存数)放到Redis里,避免每次都查数据库,减轻DB压力。
实战例子

  • 商品详情页:用户访问时先查Redis,Redis没有再查DB,查到后回写Redis(设置过期时间,比如10分钟);
  • 库存数:扣库存前先查Redis中的库存,扣减时先更Redis,再异步同步到DB(秒杀场景)。
    核心代码(库存缓存)
// 查库存(先查缓存)
public int getStock(Long skuId) {
    String key = "stock:" + skuId;
    // 1. 查Redis
    String stockStr = redisTemplate.opsForValue().get(key);
    if (stockStr != null) {
        return Integer.parseInt(stockStr);
    }
    // 2. Redis没有,查DB
    int stock = stockMapper.selectStockBySkuId(skuId);
    // 3. 回写Redis(过期时间10分钟)
    redisTemplate.opsForValue().set(key, String.valueOf(stock), 10, TimeUnit.MINUTES);
    return stock;
}

2. 限流熔断(防系统被打垮)

核心思路:限制每秒请求数,超出的请求直接拒绝;服务异常时熔断,避免雪崩。
常用工具:Guava RateLimiter(本地限流)、Sentinel/Spring Cloud Gateway(分布式限流)。
实战例子(秒杀接口限流)

// 初始化限流器:每秒最多处理1000个请求
private final RateLimiter rateLimiter = RateLimiter.create(1000.0);

@PostMapping("/seckill")
public String seckill(Long skuId) {
    // 1. 尝试获取令牌,获取不到直接返回
    if (!rateLimiter.tryAcquire()) {
        return "请求太火爆,请稍后再试";
    }
    // 2. 执行业务逻辑
    seckillService.doSeckill(skuId);
    return "秒杀成功";
}

3. 分布式锁(防超卖/重复下单)

核心思路:用Redis/ZooKeeper做分布式锁,保证同一商品的库存扣减只有一个线程执行。
实战例子(扣库存防超卖)

public boolean deductStock(Long skuId) {
    String lockKey = "lock:stock:" + skuId;
    // 1. 获取分布式锁(过期时间30秒,防死锁)
    Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "LOCK", 30, TimeUnit.SECONDS);
    if (Boolean.FALSE.equals(locked)) {
        return false; // 有其他线程在扣库存,直接返回
    }
    try {
        // 2. 查库存(DB)
        int stock = stockMapper.selectStockBySkuId(skuId);
        if (stock <= 0) {
            return false; // 库存不足
        }
        // 3. 扣库存
        stockMapper.deductStock(skuId);
        // 4. 更新Redis库存
        redisTemplate.opsForValue().decrement("stock:" + skuId);
        return true;
    } finally {
        // 5. 释放锁
        redisTemplate.delete(lockKey);
    }
}

4. 异步处理(削峰填谷)

核心思路:把非实时的操作(比如生成订单、发送短信)放到MQ(RocketMQ/Kafka)里,异步处理,快速返回请求。
实战例子(创建订单)

@PostMapping("/createOrder")
public String createOrder(OrderDTO orderDTO) {
    // 1. 生成订单ID
    String orderId = UUID.randomUUID().toString();
    orderDTO.setOrderId(orderId);
    // 2. 发送MQ消息,异步创建订单
    rocketMQTemplate.send("create-order-topic", MessageBuilder.withPayload(orderDTO).build());
    // 3. 快速返回,不用等订单创建完成
    return "订单提交成功,订单号:" + orderId;
}

// MQ消费者(异步处理订单)
@Service
@RocketMQMessageListener(topic = "create-order-topic", consumerGroup = "order-group")
public class OrderConsumer implements RocketMQListener<OrderDTO> {
    @Override
    public void onMessage(OrderDTO orderDTO) {
        // 异步创建订单、扣库存、记录日志
        orderService.createOrder(orderDTO);
    }
}

5. 数据库优化(底层保障)

核心思路:减少DB压力,提升查询/写入效率。

  • 分库分表:订单表按用户ID分表(比如分100张表),避免单表数据量过大;
  • 索引优化:给商品ID、订单号等高频查询字段加索引;
  • 读写分离:读请求走从库,写请求走主库。

三、核心方案总结

  1. 缓存兜底:Redis缓存高频数据(商品、库存),减少DB访问;
  2. 限流熔断:限制请求数,防系统过载,常用Sentinel/RateLimiter;
  3. 分布式锁:Redis/ZK保证库存扣减、订单创建的原子性,防超卖;
  4. 异步处理:MQ削峰,异步处理订单、短信等非实时操作;
  5. DB优化:分库分表、读写分离、索引优化,夯实底层。

关键点回顾

  1. 电商高并发核心是“减压力、防超卖、削峰值”;
  2. 优先用缓存+限流快速降压力,分布式锁解决数据一致性,MQ削峰填谷;
  3. 所有方案最终要落地到“保护数据库”,避免DB成为瓶颈。
posted on 2026-01-27 15:50  (Play)  阅读(0)  评论(0)    收藏  举报