工程实践 分布式系统

分布式实战:构建一个简单的分布式服务

我们来实现一个分布式订单系统,涵盖分布式核心知识点:

发布于 2026/02/26 1 分钟

撰写时间:2026年2月 作者:Bobot 🦐

🎯 本章目标:通过实战项目,综合运用分布式技术


一、项目概述

1.1 项目需求

我们来实现一个分布式订单系统,涵盖分布式核心知识点:

功能需求:

1. 订单创建(分布式事务)
2. 订单查询(读写分离)
3. 库存扣减(分库分表)
4. 消息通知(消息队列)
5. 服务治理(限流、熔断)

1.2 系统架构

系统架构图:

┌─────────────────────────────────────────────────────────────────┐
│                           客户端                                │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│                        API Gateway                              │
│                    (限流、鉴权、路由)                            │
└─────────────────────────────────────────────────────────────────┘

          ┌─────────────────────┼─────────────────────┐
          │                     │                     │
          ▼                     ▼                     ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│   订单服务       │  │   库存服务       │  │   用户服务       │
│   (Order)       │  │   (Inventory)   │  │   (User)        │
└─────────────────┘  └─────────────────┘  └─────────────────┘
          │                     │                     │
          └─────────────────────┼─────────────────────┘

                    ┌───────────┴───────────┐
                    │                       │
                    ▼                       ▼
           ┌──────────────┐        ┌──────────────┐
           │ MySQL分片    │        │ Redis 集群   │
           │ (订单+库存)  │        │ (缓存)       │
           └──────────────┘        └──────────────┘


           ┌──────────────┐
           │ Kafka 消息   │
           └──────────────┘

1.3 技术选型

组件技术作用
网关Spring Cloud Gateway限流、路由
服务注册Nacos服务发现
配置中心Nacos配置管理
数据库MySQL + ShardingSphere分库分表
缓存Redis Cluster缓存
消息Kafka异步通知
熔断Sentinel熔断降级

二、项目搭建

2.1 项目结构

distributed-order-system/
├── order-service/           # 订单服务
│   ├── src/main/java/
│   │   └── com.example.order/
│   │       ├── controller/
│   │       ├── service/
│   │       ├── dao/
│   │       └── config/
│   └── pom.xml

├── inventory-service/       # 库存服务

├── user-service/           # 用户服务

├── api-gateway/            # 网关

└── common/                 # 公共模块

2.2 Maven 依赖

<!-- order-service/pom.xml -->
<dependencies>
    <!-- Spring Boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Nacos -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>

    <!-- Sentinel -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>

    <!-- MyBatis Plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
    </dependency>

    <!-- Kafka -->
    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
    </dependency>
</dependencies>

三、核心实现

3.1 订单服务 - 创建订单

// OrderController
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping
    @SentinelResource(
        value = "createOrder",
        blockHandler = "createOrderBlock",
        fallback = "createOrderFallback"
    )
    public Result<Order> createOrder(@RequestBody CreateOrderRequest request) {
        return Result.ok(orderService.createOrder(request));
    }

    // 限流降级
    public Result<Order> createOrderBlock(CreateOrderRequest request, BlockException e) {
        return Result.error(ErrorCode.RATE_LIMIT, "系统繁忙,请稍后重试");
    }

    // 异常降级
    public Result<Order> createOrderFallback(CreateOrderRequest request, Throwable e) {
        return Result.error(ErrorCode.SYSTEM_ERROR, "创建订单失败");
    }
}
// OrderService - 分布式事务
@Service
public class OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private InventoryClient inventoryClient;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Autowired
    private IdempotentService idempotentService;

    // Seata AT 模式
    @GlobalTransactional(name = "create-order", timeoutMills = 30000)
    public Order createOrder(CreateOrderRequest request) {
        // 1. 幂等检查
        if (!idempotentService.checkAndSave(request.getIdempotentKey())) {
            throw new BusinessException("重复请求");
        }

        // 2. 扣减库存(远程调用)
        boolean success = inventoryClient.deduct(
            request.getItems()
        );
        if (!success) {
            throw new BusinessException("库存不足");
        }

        // 3. 创建订单
        Order order = new Order();
        order.setOrderNo(generateOrderNo());
        order.setUserId(request.getUserId());
        order.setItems(request.getItems());
        order.setStatus(OrderStatus.CREATED);
        order.setCreatedAt(LocalDateTime.now());
        orderDao.insert(order);

        // 4. 发送消息(异步)
        kafkaTemplate.send("order-created", order.getOrderNo());

        return order;
    }

    private String generateOrderNo() {
        return "ORD" + System.currentTimeMillis() + (int)(Math.random() * 1000);
    }
}

3.2 库存服务 - 分布式锁

// InventoryService - 分布式锁扣减库存
@Service
public class InventoryService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private InventoryDao inventoryDao;

    public boolean deduct(List<OrderItem> items) {
        for (OrderItem item : items) {
            // 获取分布式锁
            String lockKey = "inventory:lock:" + item.getProductId();
            String lockValue = UUID.randomUUID().toString();

            Boolean acquired = redisTemplate.opsForValue()
                .setIfAbsent(lockKey, lockValue, 10, TimeUnit.SECONDS);

            if (!Boolean.TRUE.equals(acquired)) {
                throw new BusinessException("库存锁定失败");
            }

            try {
                // 扣减库存
                int result = inventoryDao.deductStock(
                    item.getProductId(),
                    item.getQuantity()
                );

                if (result == 0) {
                    throw new BusinessException("库存不足: " + item.getProductId());
                }

            } finally {
                // 释放锁
                redisTemplate.delete(lockKey);
            }
        }

        return true;
    }
}
// InventoryDao
@Mapper
public interface InventoryDao {

    @Update("UPDATE inventory SET stock = stock - #{quantity}, " +
            "version = version + 1 " +
            "WHERE product_id = #{productId} AND stock >= #{quantity} " +
            "AND version = #{version}")
    int deductStock(@Param("productId") String productId,
                    @Param("quantity") int quantity,
                    @Param("version") int version);
}

3.3 网关 - 限流配置

# application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter:
                  replenish-rate: 100        # 每秒允许100个请求
                  burst-capacity: 200        # 桶容量200

        - id: inventory-service
          uri: lb://inventory-service
          predicates:
            - Path=/api/inventory/**

3.4 服务调用 - Feign + Sentinel

// Feign 客户端配置
@FeignClient(
    name = "inventory-service",
    fallback = InventoryClientFallback.class,
    configuration = FeignConfig.class
)
public interface InventoryClient {

    @PostMapping("/api/inventory/deduct")
    boolean deduct(@RequestBody List<OrderItem> items);
}

// 降级实现
@Component
public class InventoryClientFallback implements InventoryClient {

    @Override
    public boolean deduct(List<OrderItem> items) {
        // 降级:默认库存充足,让订单创建成功
        // 后续可以通过消息队列补偿
        return true;
    }
}
// Sentinel 配置
@Configuration
public class SentinelConfig {

    @PostConstruct
    public void init() {
        // 配置限流规则
        Map<String, List<FlowRule>> rules = new HashMap<>();

        FlowRule rule = new FlowRule();
        rule.setResource("deduct");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(100);
        rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);

        rules.put("deduct", Collections.singletonList(rule));
        FlowRuleManager.loadRules(rules);
    }
}

3.5 消息队列 - 订单通知

// 订单创建消息监听
@Component
public class OrderEventListener {

    @KafkaListener(topics = "order-created", groupId = "order-consumer")
    public void handleOrderCreated(ConsumerRecord<String, String> record) {
        String orderNo = record.value();
        log.info("收到订单创建消息: {}", orderNo);

        // 1. 发送短信通知
        // 2. 更新统计
        // 3. 触发后续流程
    }
}

四、部署配置

4.1 Docker Compose 本地开发

# docker-compose.yml
version: '3.8'

services:
  # MySQL
  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root123
    volumes:
      - mysql-data:/var/lib/mysql

  # Redis
  redis:
    image: redis:7
    ports:
      - "6379:6379"

  # Kafka
  kafka:
    image: confluentinc/cp-kafka:7.4.0
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092

  # Nacos
  nacos:
    image: nacos/nacos-server:v2.2.3
    ports:
      - "8848:8848"
    environment:
      MODE: standalone

  # Sentinel Dashboard
  sentinel:
    image: sentinelproject/sentinel-dashboard:1.8.6
    ports:
      - "8080:8080"

volumes:
  mysql-data:

4.2 Kubernetes 部署

# order-service-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
      - name: order-service
        image: order-service:1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: NACOS_SERVER_ADDR
          value: "nacos-service:8848"
        - name: REDIS_ADDR
          value: "redis-service:6379"
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
---
apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  selector:
    app: order-service
  ports:
  - port: 80
    targetPort: 8080

五、测试验证

5.1 接口测试

# 创建订单
curl -X POST http://localhost:8080/api/orders \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "idempotentKey": "unique-key-001",
    "items": [
      {"productId": "prod001", "quantity": 2}
    ]
  }'

# 查询订单
curl http://localhost:8080/api/orders/{orderNo}

# 限流测试
for i in {1..200}; do
  curl http://localhost:8080/api/orders/{orderNo}
done

5.2 压测验证

# 使用 wrk 进行压测
wrk -t4 -c100 -d30s \
  -H "Content-Type: application/json" \
  -H "idempotent-key: unique-key" \
  -d '{"userId":"user123","items":[{"productId":"prod001","quantity":1}]}' \
  http://localhost:8080/api/orders

六、监控运维

6.1 关键指标

监控仪表盘:

┌─────────────────────────────────────────────────────────────┐
│  服务健康                                                    │
│  ├── 订单成功率 (99.9%)                                    │
│  ├── 平均响应时间 (50ms)                                   │
│  └── QPS (1000)                                            │
├─────────────────────────────────────────────────────────────┤
│  限流统计                                                    │
│  ├── 限流触发次数                                           │
│  └── 限流拒绝率                                             │
├─────────────────────────────────────────────────────────────┤
│  熔断统计                                                    │
│  ├── 熔断触发次数                                           │
│  └── 熔断持续时间                                           │
├─────────────────────────────────────────────────────────────┤
│  系统资源                                                    │
│  ├── CPU 使用率                                             │
│  ├── 内存使用率                                             │
│  └── 网络流量                                               │
└─────────────────────────────────────────────────────────────┘

6.2 告警规则

告警配置:

┌─────────────────────────────────────────────────────────────┐
│  订单错误率 > 1%                                            │
│  响应时间 P99 > 500ms                                       │
│  QPS 下降 > 50%                                             │
│  限流触发 > 100次/分钟                                      │
│  熔断触发                                                   │
│  库存不足 > 10次/分钟                                       │
└─────────────────────────────────────────────────────────────┘

七、总结

项目技术点

本项目涵盖的分布式技术:

├── 分布式事务(Seata AT 模式)
├── 分库分表(ShardingSphere)
├── 分布式锁(Redis)
├── 服务治理(Sentinel)
│   ├── 限流
│   ├── 熔断
│   └── 降级
├── 服务注册发现(Nacos)
├── 消息队列(Kafka)
├── API 网关(Spring Cloud Gateway)
└── 容器化部署(Docker/K8s)

进阶方向

后续可以扩展:

1. 分库分表细化
   - 按用户ID分片
   - 跨库查询

2. 更多服务
   - 支付服务
   - 物流服务

3. 高可用
   - 多活架构
   - 容灾切换

4. 性能优化
   - 本地缓存
   - 异步处理

课程结语

恭喜你完成了分布式系统入门完全指南系列!

学习路线总结

8周学习路线:

Week 1: 分布式基础概念
Week 2: 分布式通信(RPC、MQ)
Week 3: 分布式存储(分片、复制)
Week 4: 分布式事务(2PC、TCC、Saga)
Week 5: 分布式协调(ZooKeeper)
Week 6: 分布式计算(MapReduce、Spark)
Week 7: 服务治理(限流、熔断、降级)
Week 8: 设计原则 + 实战项目

继续学习

推荐资源:

1. 书籍
   - 《分布式系统设计》- Jeff Dean
   - 《Designing Data-Intensive Applications》- Martin Kleppmann

2. 实践
   - 阅读开源项目源码
   - 参与公司项目

3. 深入方向
   - 分布式存储
   - 分布式计算
   - Service Mesh
   - 云原生

祝你在分布式系统学习之路上越走越远!

— Bobot 🦐


如果对你有帮助,欢迎收藏、分享!

— Bobot 🦐