作者
发布于 2026-03-03 / 1 阅读
0

电商微服务架构

概述

基于企业级电商平台(Spring Cloud Alibaba 微服务架构)的实战经验。涵盖从基础架构设计到高并发场景、从分布式事务到性能优化的全方位技术考察点。


一、微服务架构基础

1.1 为什么选择微服务架构?

问题:单体应用 vs 微服务,什么情况下应该选择微服务?

核心要点

  • 团队规模:微服务适合 50+ 人的研发团队,按业务域拆分团队
  • 业务复杂度:电商涉及商品、订单、支付、库存等多个独立业务域
  • 技术异构性:不同服务可选择最适合的技术栈
  • 独立部署:订单服务升级不影响商品服务

电商场景示例

单体痛点:
- 代码库 100万+ 行,构建时间 30分钟+
- 小改动需要全量发布
- 库存高峰拖垮整个系统

微服务收益:
- 订单服务独立扩容应对大促
- 商品服务静态化 + CDN 加速
- 库存服务 Redis 抗高并发

1.2 微服务拆分原则

问题:如何合理拆分微服务?拆得太细或太粗各有什么问题?

拆分原则

原则说明示例
业务边界按 DDD 限界上下文拆分订单、商品、用户、支付
数据独立性每个服务独立数据库订单表不在商品库
团队规模2个披萨团队原则6-10人维护一个服务
变更频率高频变更独立拆分促销服务单独部署

拆分粒度问题

  • 过细:分布式事务复杂度上升,网络开销增加
  • 过粗:失去微服务独立部署、独立扩容的优势

电商服务拆分示例

✅ 合理拆分:
- user-service(用户)
- product-service(商品)
- order-service(订单)
- payment-service(支付)
- inventory-service(库存)
- promotion-service(促销)

❌ 过度拆分:
- user-profile-service
- user-address-service
- user-coupon-service
(应该合并为 user-service)

1.3 服务间通信方式

问题:微服务间同步调用和异步消息如何选择?

决策矩阵

场景推荐方式说明
用户注册发送短信异步消息非核心流程,允许延迟
下单扣减库存同步调用强一致性要求
订单支付成功通知异步消息最终一致性即可
获取商品详情同步调用实时性要求高

电商最佳实践

// 同步调用 - Feign 客户端
@FeignClient(name = "inventory-service")
public interface InventoryClient {
    @PostMapping("/inventory/deduct")
    Result<Boolean> deduct(@RequestBody DeductRequest request);
}

// 异步消息 - RocketMQ
@RocketMQMessageListener(topic = "order-paid", consumerGroup = "inventory-consumer")
public class InventoryConsumer implements RocketMQListener<OrderPaidEvent> {
    @Override
    public void onMessage(OrderPaidEvent event) {
        // 异步扣减库存
    }
}

二、分布式事务

2.1 分布式事务解决方案对比

问题:电商下单场景(扣库存、创订单、扣余额)如何保证数据一致性?

方案对比

方案一致性性能复杂度适用场景
2PC强一致传统数据库XA
TCC最终一致电商核心交易
Saga最终一致长事务流程
本地消息表最终一致异步场景
Seata AT最终一致简单CRUD场景

电商推荐方案

核心链路(强一致性):TCC
- Try:预留库存、预扣余额
- Confirm:确认扣减
- Cancel:释放预留

非核心链路(最终一致):RocketMQ事务消息
- 订单创建成功发送消息
- 积分服务消费增加积分

2.2 TCC 实现细节

问题:TCC 的 Try、Confirm、Cancel 分别做什么?空回滚和幂等如何解决?

TCC 三阶段

@Component
public class InventoryTccAction {
    
    // Try:预留资源
    @Transactional
    public boolean tryDeduct(String xid, Long productId, Integer count) {
        // 1. 检查库存
        // 2. 扣减可售库存
        // 3. 增加冻结库存
        // 4. 记录事务日志
    }
    
    // Confirm:确认执行
    @Transactional
    public boolean confirm(String xid) {
        // 1. 删除事务日志
        // 2. 扣减冻结库存(实际扣减)
    }
    
    // Cancel:取消回滚
    @Transactional
    public boolean cancel(String xid) {
        // 1. 查询事务日志
        // 2. 恢复可售库存
        // 3. 扣减冻结库存
        // 4. 删除事务日志
    }
}

异常处理

  • 空回滚:Try 未执行时 Cancel 被调用,需记录事务状态
  • 幂等控制:Confirm/Cancel 可能被重复调用,需保证幂等
  • 悬挂:Cancel 先于 Try 执行,需检查事务状态

三、高并发与性能优化

3.1 秒杀系统设计

问题:如何设计一个支持 10万 QPS 的秒杀系统?

分层优化策略

┌─────────────────────────────────────────┐
│  前端层                                  │
│  - 静态页面 CDN                          │
│  - 秒杀按钮置灰/倒计时                    │
│  - 验证码/滑块防刷                        │
└─────────────────────────────────────────┘
                   │
┌─────────────────────────────────────────┐
│  网关层                                  │
│  - Nginx 限流(漏桶算法)                 │
│  - Sentinel 热点参数限流                  │
│  - 黑名单过滤                             │
└─────────────────────────────────────────┘
                   │
┌─────────────────────────────────────────┐
│  应用层                                  │
│  - 令牌桶限流(Redis List)               │
│  - 库存预热(Redis)                      │
│  - Lua 原子扣减                          │
│  - 异步下单(RocketMQ)                   │
└─────────────────────────────────────────┘
                   │
┌─────────────────────────────────────────┐
│  数据层                                  │
│  - 库存分片(多 Redis 节点)              │
│  - 写保护(限流 + 队列)                  │
└─────────────────────────────────────────┘

核心代码

-- Redis Lua 原子扣减库存
local stock = redis.call('get', KEYS[1])
if tonumber(stock) <= 0 then
    return -1  -- 库存不足
end
redis.call('decr', KEYS[1])
return redis.call('get', KEYS[1])  -- 返回剩余库存

3.2 缓存设计

问题:多级缓存如何设计?缓存穿透、击穿、雪崩如何解决?

多级缓存架构

请求 → Caffeine(L1,本地)→ Redis(L2,分布式)→ DB
         ↓                      ↓
      1ms响应                5ms响应
      单机10万QPS            集群10万QPS

缓存问题解决方案

问题现象解决方案
穿透查询不存在数据,直达DB布隆过滤器 / 空值缓存
击穿热点Key过期,瞬间大量请求到DB互斥锁 / 逻辑过期
雪崩大量Key同时过期随机过期时间 / 多级缓存

电商缓存策略

@Component
public class ProductCache {
    
    @Cacheable(value = "product", key = "#id", 
               unless = "#result == null")
    public Product getProduct(Long id) {
        return productMapper.selectById(id);
    }
    
    // 布隆过滤器防止穿透
    public Product getProductWithBloomFilter(Long id) {
        if (!bloomFilter.mightContain(id)) {
            return null;  // 一定不存在
        }
        return getProduct(id);
    }
}

3.3 数据库优化

问题:订单表数据量过亿,如何优化查询性能?

分库分表策略

维度策略说明
分库用户ID取模user_id % 2 = 0/1
分表时间范围 + 取模按月分表,每月16张
路由ShardingSphere-JDBC透明化分片

订单表分片示例

# ShardingSphere 配置
sharding:
  tables:
    t_order:
      actualDataNodes: ds${0..1}.t_order_${2024..2025}_${1..12}
      tableStrategy:
        standard:
          shardingColumn: create_time
          preciseAlgorithm: TimeShardingAlgorithm
      databaseStrategy:
        standard:
          shardingColumn: user_id
          preciseAlgorithm: UserIdShardingAlgorithm

慢SQL优化 checklist

  • 索引覆盖查询(Using index)
  • 避免 SELECT *
  • 大分页使用游标/延迟关联
  • 深分页优化(limit 1000000, 10 → 延迟关联)

四、高可用与容灾

4.1 服务熔断降级

问题:下游服务故障时,如何保证系统可用性?

熔断器状态机

┌─────────┐    失败率>阈值     ┌─────────┐
│  CLOSED │ ─────────────────→ │  OPEN   │
│ (正常)  │                    │ (熔断)  │
└────┬────┘                    └────┬────┘
     │    ←───────────────────     │
     │      超时后半开               │
     │                             │
     └─────────────────────────────┘
              半开状态(HALF_OPEN)

Sentinel 配置示例

// 熔断降级规则
DegradeRule rule = new DegradeRule();
rule.setResource("getProduct");
rule.setGrade(CircuitBreakerStrategy.ERROR_RATIO);  // 异常比例
rule.setCount(0.5);  // 50% 异常率触发熔断
rule.setTimeWindow(30);  // 熔断30秒
rule.setMinRequestAmount(10);  // 最小请求数

4.2 限流策略

问题:大促期间如何保护系统不被流量打垮?

限流算法对比

算法优点缺点适用场景
计数器简单突刺问题简单限流
滑动窗口平滑内存占用精准限流
令牌桶允许突发实现复杂秒杀场景
漏桶绝对平滑无突发流量整形

电商限流实践

// 网关层限流 - 基于 IP
GatewayFilterSpec filterSpec = builder.routes()
    .route("order_route", r -> r.path("/order/**")
        .filters(f -> f.requestRateLimiter(config -> {
            config.setRateLimiter(redisRateLimiter());
            config.setKeyResolver(exchange -> 
                Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()));
        }))
        .uri("lb://order-service"));

4.3 多活架构

问题:如何实现异地多活?数据一致性如何处理?

多活架构层级

层级同城双活异地多活
接入层DNS 轮询智能 DNS(按地域)
应用层双机房部署单元化部署
数据层主从同步双向同步 / 分片

数据一致性策略

读多写少场景(商品信息):
- 最终一致性,多机房同步延迟 < 1s

强一致场景(库存、余额):
- 单机房写,跨机房读
- 或 Paxos/Raft 分布式共识

五、可观测性

5.1 链路追踪

问题:微服务调用链复杂,如何快速定位问题?

SkyWalking 链路追踪

用户请求 → Gateway → Order → Payment → Inventory
   │          │        │         │          │
   └──────────┴────────┴─────────┴──────────┘
              TraceID: abc123
              
Span 层级:
- Gateway: 10ms
  - Order: 50ms
    - Payment: 30ms
    - Inventory: 15ms

关键指标

  • P99 延迟:99% 请求响应时间 < 500ms
  • 错误率:< 0.1%
  • 吞吐量:> 10000 QPS

5.2 监控告警

问题:如何构建有效的监控告警体系?

监控分层

层级工具监控内容
基础设施PrometheusCPU、内存、磁盘、网络
应用指标MicrometerQPS、延迟、错误率
业务指标自定义订单量、支付成功率
日志ELK错误日志、慢查询

告警规则示例

# Prometheus 告警规则
groups:
  - name: ecommerce-alerts
    rules:
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.01
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "错误率超过 1%"

六、安全架构

6.1 认证授权

问题:微服务架构下如何实现统一认证授权?

JWT + Gateway 方案

┌─────────┐    登录     ┌─────────┐    JWT Token    ┌─────────┐
│  客户端  │ ─────────→ │ 用户服务 │ ─────────────→ │  客户端  │
└─────────┘            └─────────┘                 └─────────┘
     │
     │ 携带 JWT
     ▼
┌─────────┐   验签    ┌─────────┐   转发    ┌─────────┐
│  Gateway │ ───────→ │  业务服务 │ ←──────→ │  数据库  │
│ (验Token)│          │ (鉴权限) │          │         │
└─────────┘          └─────────┘          └─────────┘

权限设计

@PreAuthorize("hasRole('ADMIN') or hasPermission(#orderId, 'ORDER:VIEW')")
public Order getOrder(Long orderId) {
    return orderService.getOrder(orderId);
}

6.2 防刷防攻击

问题:如何防止接口被恶意刷量?

防护策略

层级措施实现
网关层IP 限流Nginx limit_req
应用层用户限流Redis + Lua
业务层验证码图形/短信/滑块
数据层请求签名HMAC + 时间戳

防重放攻击

public class AntiReplayFilter {
    public boolean validateRequest(String sign, String timestamp, String nonce) {
        // 1. 时间戳校验(5分钟内有效)
        long now = System.currentTimeMillis();
        if (now - Long.parseLong(timestamp) > 300000) {
            return false;
        }
        
        // 2. nonce 去重(Redis SetNX)
        if (!redis.setnx("nonce:" + nonce, "1", 300, TimeUnit.SECONDS)) {
            return false;
        }
        
        // 3. 签名验证
        String expectedSign = HmacUtils.hmacSha256Hex(key, timestamp + nonce);
        return expectedSign.equals(sign);
    }
}

七、面试技巧总结

7.1 回答框架(STAR法则)

Situation(场景):什么场景下遇到的问题?
Task(任务):你的任务/目标是什么?
Action(行动):你采取了哪些行动?
Result(结果):最终效果如何?

示例

"在 2024 年双 11 大促期间(S),我们的订单服务峰值达到了 5万 QPS,数据库连接池频繁耗尽(T)。我引入了 Redis 缓存 + 异步下单方案(A),将数据库压力降低了 80%,成功支撑了峰值流量(R)。"

7.2 加分项

能力体现方式
全栈视野从前端到数据库的完整链路理解
数据驱动用具体数字说明优化效果
故障经验真实的线上故障排查经历
持续学习关注云原生、ServiceMesh 等新技术

7.3 避坑指南

避免回答

  • "我们用了微服务,因为流行"
  • "分布式事务用 2PC,因为简单"
  • "缓存用 Redis,因为快"

正确回答

  • "微服务拆分基于 DDD,按业务边界划分..."
  • "对比了 Seata AT/TCC/Saga,最终选择 TCC 因为..."
  • "Redis 用于热点数据缓存,配合本地缓存 Caffeine..."

八、实战场景题

场景 1:订单超时自动取消

问题:下单后 30 分钟未支付,如何自动取消订单并恢复库存?

方案对比

方案实现优缺点
定时任务XXL-Job 每分钟扫描简单,但存在延迟
延迟队列RocketMQ 延迟消息精确触发,推荐
Redis 过期Key 过期监听不可靠,不推荐

推荐实现

// 发送延迟消息
rocketMQTemplate.asyncSend("order-delay-topic", 
    MessageBuilder.withPayload(order).build(), 
    new SendCallback() {...}, 
    300000,  // 延迟5分钟
    3        // 延迟级别
);

// 消费超时消息
@RocketMQMessageListener(topic = "order-delay-topic", 
                        consumerGroup = "order-timeout-consumer")
public class OrderTimeoutConsumer implements RocketMQListener<Order> {
    @Override
    public void onMessage(Order order) {
        // 1. 查询订单状态
        // 2. 未支付则取消订单
        // 3. 恢复库存
    }
}

场景 2:库存扣减与回滚

问题:下单时扣了库存,用户取消订单后如何回滚?

状态机设计

┌─────────┐    下单     ┌─────────┐    支付     ┌─────────┐
│  可用   │ ─────────→ │  冻结   │ ─────────→ │  已扣减 │
│  100    │   扣10     │  90/10  │   确认     │   90    │
└────┬────┘            └────┬────┘            └─────────┘
     │                      │
     │    取消订单           │
     └──────────────────────┘
              回滚

总结

本文从微服务基础、分布式事务、高并发优化、高可用容灾、可观测性、安全架构等维度,整理了电商架构师面试的核心问题。掌握这些知识点,结合实际项目经验,能够在架构师面试中展现出扎实的技术功底和系统设计能力。

核心要点回顾

  1. 微服务拆分:按业务边界,避免过度拆分
  2. 分布式事务:TCC 用于核心链路,消息用于最终一致
  3. 高并发:多级缓存 + 异步化 + 限流熔断
  4. 高可用:熔断降级 + 多活架构 + 容灾演练
  5. 可观测性:链路追踪 + 指标监控 + 日志聚合