分布式系统实战:电商平台架构演进
CSDN分布式系统深度实战系列:一个电商平台从单体架构到分布式微服务架构的全过程演进。涵盖技术选型、架构设计、数据迁移、性能优化四大核心模块,每个阶段都配有真实的业务场景、架构图和性能数据对比。通过订单系统、库存系统、支付系统等核心模块的演进案例,展示如何构建高可用、可扩展的电商平台架构。建议⭐收藏⭐,架构演进时随时参考!
🏗️ 电商平台架构演进全景图
一、🚀 第一阶段:单体架构(日订单<1000)
1.1 技术栈与架构设计
// 单体应用结构 - Spring Boot + MySQL
@SpringBootApplication
public class MonolithEcommerceApplication {public static void main(String[] args) {SpringApplication.run(MonolithEcommerceApplication.class, args);}
}// 单体应用包结构
src/main/java/com/ebusiness/
├── controller/ # 控制层
│ ├── UserController.java
│ ├── ProductController.java
│ └── OrderController.java
├── service/ # 业务层
│ ├── UserService.java
│ ├── ProductService.java
│ └── OrderService.java
├── repository/ # 数据层
│ ├── UserRepository.java
│ ├── ProductRepository.java
│ └── OrderRepository.java
└── entity/ # 实体类├── User.java├── Product.java└── Order.java
1.2 数据库设计
-- 单一数据库设计
CREATE DATABASE ecommerce_monolith;-- 用户表
CREATE TABLE users (id BIGINT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) UNIQUE NOT NULL,email VARCHAR(100) UNIQUE NOT NULL,password_hash VARCHAR(100) NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,INDEX idx_username (username),INDEX idx_email (email)
);-- 商品表
CREATE TABLE products (id BIGINT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(200) NOT NULL,price DECIMAL(10,2) NOT NULL,stock INT NOT NULL,category_id BIGINT,status TINYINT DEFAULT 1,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,INDEX idx_category (category_id),INDEX idx_status (status)
);-- 订单表
CREATE TABLE orders (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL,total_amount DECIMAL(10,2) NOT NULL,status ENUM('PENDING','PAID','SHIPPED','COMPLETED','CANCELLED') DEFAULT 'PENDING',created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,FOREIGN KEY (user_id) REFERENCES users(id),INDEX idx_user_id (user_id),INDEX idx_status (status),INDEX idx_created_at (created_at)
);-- 订单项表
CREATE TABLE order_items (id BIGINT PRIMARY KEY AUTO_INCREMENT,order_id BIGINT NOT NULL,product_id BIGINT NOT NULL,quantity INT NOT NULL,price DECIMAL(10,2) NOT NULL,FOREIGN KEY (order_id) REFERENCES orders(id),FOREIGN KEY (product_id) REFERENCES products(id),INDEX idx_order_id (order_id)
);
1.3 核心业务逻辑
@Service
@Transactional
@Slf4j
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate ProductRepository productRepository;@Autowiredprivate UserRepository userRepository;/*** 创建订单 - 单体架构下的简单实现*/public Order createOrder(OrderRequest request) {// 1. 验证用户User user = userRepository.findById(request.getUserId()).orElseThrow(() -> new BusinessException("用户不存在"));// 2. 验证商品和库存List<OrderItem> items = new ArrayList<>();BigDecimal totalAmount = BigDecimal.ZERO;for (OrderItemRequest itemRequest : request.getItems()) {Product product = productRepository.findById(itemRequest.getProductId()).orElseThrow(() -> new BusinessException("商品不存在"));if (product.getStock() < itemRequest.getQuantity()) {throw new BusinessException("库存不足: " + product.getName());}// 扣减库存product.setStock(product.getStock() - itemRequest.getQuantity());productRepository.save(product);// 计算订单项BigDecimal itemTotal = product.getPrice().multiply(BigDecimal.valueOf(itemRequest.getQuantity()));totalAmount = totalAmount.add(itemTotal);OrderItem item = new OrderItem();item.setProductId(product.getId());item.setQuantity(itemRequest.getQuantity());item.setPrice(product.getPrice());items.add(item);}// 3. 创建订单Order order = new Order();order.setUserId(user.getId());order.setTotalAmount(totalAmount);order.setStatus(OrderStatus.PENDING);order.setItems(items);Order savedOrder = orderRepository.save(order);log.info("订单创建成功: {}", savedOrder.getId());return savedOrder;}
}
二、💡 第二阶段:垂直拆分(日订单1万-10万)
2.1 服务拆分策略
// 用户服务 - 独立部署
@Service
@Slf4j
public class UserService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate RedisTemplate<String, User> redisTemplate;private static final String USER_CACHE_PREFIX = "user:";private static final Duration CACHE_TTL = Duration.ofHours(1);public User getUser(Long userId) {// 缓存优化String cacheKey = USER_CACHE_PREFIX + userId;User user = redisTemplate.opsForValue().get(cacheKey);if (user != null) {return user;}user = userRepository.findById(userId).orElseThrow(() -> new BusinessException("用户不存在"));redisTemplate.opsForValue().set(cacheKey, user, CACHE_TTL);return user;}
}// 商品服务 - 独立部署
@Service
@Slf4j
public class ProductService {@Autowiredprivate ProductRepository productRepository;@Autowiredprivate RedisTemplate<String, Product> redisTemplate;/*** 商品查询 - 加入缓存和搜索优化*/public Page<Product> searchProducts(ProductQuery query, Pageable pageable) {// 复杂的商品搜索逻辑Specification<Product> spec = (root, criteriaQuery, criteriaBuilder) -> {List<Predicate> predicates = new ArrayList<>();if (StringUtils.isNotBlank(query.getKeyword())) {Predicate namePredicate = criteriaBuilder.like(root.get("name"), "%" + query.getKeyword() + "%");Predicate descPredicate = criteriaBuilder.like(root.get("description"), "%" + query.getKeyword() + "%");predicates.add(criteriaBuilder.or(namePredicate, descPredicate));}if (query.getCategoryId() != null) {predicates.add(criteriaBuilder.equal(root.get("categoryId"), query.getCategoryId()));}if (query.getMinPrice() != null && query.getMaxPrice() != null) {predicates.add(criteriaBuilder.between(root.get("price"), query.getMinPrice(), query.getMaxPrice()));}return criteriaBuilder.and(predicates.toArray(new Predicate[0]));};return productRepository.findAll(spec, pageable);}
}
2.2 数据库垂直拆分
-- 用户数据库
CREATE DATABASE user_db;
CREATE TABLE users (...); -- 同单体架构,但独立数据库-- 商品数据库
CREATE DATABASE product_db;
CREATE TABLE products (...);
CREATE TABLE categories (...);
CREATE TABLE product_skus (...);-- 订单数据库
CREATE DATABASE order_db;
CREATE TABLE orders (...);
CREATE TABLE order_items (...);
2.3 服务间通信 - RESTful API
// 订单服务调用用户服务
@Service
public class OrderService {@Autowiredprivate RestTemplate restTemplate;private static final String USER_SERVICE_URL = "http://user-service/api/users";private static final String PRODUCT_SERVICE_URL = "http://product-service/api/products";/*** 跨服务创建订单*/public Order createOrderDistributed(OrderRequest request) {// 1. 调用用户服务验证用户User user = restTemplate.getForObject(USER_SERVICE_URL + "/" + request.getUserId(), User.class);if (user == null) {throw new BusinessException("用户不存在");}// 2. 调用商品服务验证库存for (OrderItemRequest itemRequest : request.getItems()) {ProductStock stock = restTemplate.getForObject(PRODUCT_SERVICE_URL + "/" + itemRequest.getProductId() + "/stock",ProductStock.class);if (stock.getAvailable() < itemRequest.getQuantity()) {throw new BusinessException("库存不足");}}// 3. 创建订单(本地事务)return createOrderLocal(request);}
}
三、⚡ 第三阶段:分布式服务(日订单10万-100万)
3.1 服务注册与发现
# Spring Cloud Eureka 配置
eureka:client:service-url:defaultZone: http://eureka1:8761/eureka,http://eureka2:8762/eurekaregister-with-eureka: truefetch-registry: trueinstance:hostname: ${spring.application.name}prefer-ip-address: true# 应用配置
spring:application:name: order-servicecloud:loadbalancer:ribbon:enabled: true
3.2 分布式事务 - Saga模式
// Saga模式实现分布式事务
@Service
@Slf4j
public class OrderSagaService {@Autowiredprivate InventoryService inventoryService;@Autowiredprivate PaymentService paymentService;@Autowiredprivate ShippingService shippingService;@Autowiredprivate SagaCoordinator sagaCoordinator;/*** 创建订单Saga事务*/@Sagapublic OrderResult createOrderSaga(OrderRequest request) {SagaExecution saga = new SagaExecution("create-order");try {// 步骤1: 预留库存saga.addStep("reserve-inventory", () -> {inventoryService.reserveStock(request.getItems());}, () -> {inventoryService.releaseStock(request.getItems());});// 步骤2: 创建订单saga.addStep("create-order", () -> {return orderRepository.save(buildOrder(request));}, (order) -> {orderRepository.delete(order);});// 步骤3: 处理支付saga.addStep("process-payment", () -> {paymentService.processPayment(request.getPaymentInfo());}, (payment) -> {paymentService.refundPayment(payment);});// 执行Sagareturn saga.execute();} catch (SagaException e) {log.error("订单创建Saga失败", e);// 执行补偿操作saga.compensate();throw new BusinessException("订单创建失败");}}
}
3.3 消息队列异步化
// 订单创建消息生产者
@Component
@Slf4j
public class OrderEventProducer {@Autowiredprivate RocketMQTemplate rocketMQTemplate;/*** 发送订单创建事件*/public void sendOrderCreatedEvent(Order order) {OrderCreatedEvent event = new OrderCreatedEvent();event.setOrderId(order.getId());event.setUserId(order.getUserId());event.setTotalAmount(order.getTotalAmount());event.setItems(order.getItems());event.setCreateTime(order.getCreatedAt());rocketMQTemplate.convertAndSend("ORDER_CREATED_TOPIC", event);log.info("订单创建事件发送成功: {}", order.getId());}
}// 库存扣减消费者
@Component
@RocketMQMessageListener(topic = "ORDER_CREATED_TOPIC",consumerGroup = "inventory-consumer-group"
)
@Slf4j
public class InventoryDeductionConsumer implements RocketMQListener<OrderCreatedEvent> {@Autowiredprivate InventoryService inventoryService;@Overridepublic void onMessage(OrderCreatedEvent event) {try {log.info("收到订单创建事件,开始扣减库存: {}", event.getOrderId());inventoryService.deductStock(event.getOrderId(), event.getItems());log.info("库存扣减成功: {}", event.getOrderId());} catch (Exception e) {log.error("库存扣减失败: {}", event.getOrderId(), e);// 重试或人工处理throw new RuntimeException("库存扣减失败", e);}}
}
四、🏗️ 第四阶段:微服务架构(日订单100万+)
4.1 领域驱动设计(DDD)
// 订单聚合根
@Entity
@AggregateRoot
@Data
public class Order {@Idprivate Long id;private Long userId;private BigDecimal totalAmount;private OrderStatus status;private List<OrderItem> items;private Address shippingAddress;private PaymentInfo paymentInfo;/*** 创建订单 - 领域逻辑*/public static Order create(Long userId, List<OrderItem> items, Address address) {Order order = new Order();order.id = IdGenerator.nextId();order.userId = userId;order.items = items;order.shippingAddress = address;order.status = OrderStatus.PENDING;order.totalAmount = calculateTotalAmount(items);// 领域事件order.addDomainEvent(new OrderCreatedEvent(order.id, order.userId));return order;}/*** 支付订单*/public void pay(PaymentInfo paymentInfo) {if (this.status != OrderStatus.PENDING) {throw new IllegalStateException("订单状态异常");}this.paymentInfo = paymentInfo;this.status = OrderStatus.PAID;this.addDomainEvent(new OrderPaidEvent(this.id));}
}// 订单领域服务
@Service
@DomainService
@Slf4j
public class OrderDomainService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate DomainEventPublisher eventPublisher;/*** 处理订单创建*/@Transactionalpublic Order handleOrderCreation(CreateOrderCommand command) {// 验证业务规则validateBusinessRules(command);// 创建订单聚合Order order = Order.create(command.getUserId(),command.getItems(),command.getShippingAddress());// 保存聚合orderRepository.save(order);// 发布领域事件eventPublisher.publishAll(order.getDomainEvents());order.clearDomainEvents();return order;}
}
4.2 服务网格与治理
# Istio VirtualService - 订单服务路由
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: order-service
spec:hosts:- order-servicehttp:- match:- headers:version:exact: canaryroute:- destination:host: order-servicesubset: canaryweight: 10- route:- destination:host: order-servicesubset: stableweight: 90retries:attempts: 3perTryTimeout: 2stimeout: 10s# DestinationRule - 负载均衡策略
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: order-service
spec:host: order-servicesubsets:- name: stablelabels:version: stabletrafficPolicy:loadBalancer:simple: LEAST_CONN- name: canarylabels:version: canarytrafficPolicy:loadBalancer:simple: ROUND_ROBIN
4.3 数据分片与读写分离
// 订单分片策略
@Component
@Slf4j
public class OrderShardingStrategy {private static final int SHARD_COUNT = 16;private static final int TABLE_COUNT_PER_SHARD = 64;/*** 根据用户ID计算分片*/public String calculateShard(Long userId) {int shardIndex = (int) (userId % SHARD_COUNT);return "order_db_" + shardIndex;}/*** 根据订单ID计算表名*/public String calculateTableName(Long orderId) {int tableIndex = (int) (orderId % TABLE_COUNT_PER_SHARD);return "orders_" + tableIndex;}
}// 分片数据源路由
@Component
public class OrderDataSourceRouter extends AbstractRoutingDataSource {@Autowiredprivate OrderShardingStrategy shardingStrategy;@Overrideprotected Object determineCurrentLookupKey() {Long userId = OrderContextHolder.getCurrentUserId();if (userId == null) {return "order_db_0"; // 默认分片}return shardingStrategy.calculateShard(userId);}
}
五、📊 性能优化实战
5.1 缓存策略优化
// 多级缓存实现
@Service
@Slf4j
public class MultiLevelCacheService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// 本地缓存private Cache<String, Object> localCache = Caffeine.newBuilder().maximumSize(10000).expireAfterWrite(5, TimeUnit.MINUTES).build();/*** 获取订单信息 - 多级缓存*/public Order getOrderWithCache(Long orderId) {String cacheKey = "order:" + orderId;// 1. 查询本地缓存Order order = (Order) localCache.getIfPresent(cacheKey);if (order != null) {log.debug("命中本地缓存: {}", orderId);return order;}// 2. 查询Redis缓存order = (Order) redisTemplate.opsForValue().get(cacheKey);if (order != null) {log.debug("命中Redis缓存: {}", orderId);localCache.put(cacheKey, order);return order;}// 3. 查询数据库order = orderRepository.findById(orderId);if (order != null) {// 异步写入缓存CompletableFuture.runAsync(() -> {redisTemplate.opsForValue().set(cacheKey, order, Duration.ofHours(1));localCache.put(cacheKey, order);});}return order;}
}
5.2 数据库优化
-- 订单表分片后索引优化
CREATE TABLE order_db_0.orders_0 (id BIGINT PRIMARY KEY,user_id BIGINT NOT NULL,-- ... 其他字段INDEX idx_user_id (user_id),INDEX idx_status_created (status, created_at),INDEX idx_user_created (user_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 读写分离配置
-- 写库
spring:datasource:write:url: jdbc:mysql://master-db:3306/order_db_0username: write_userpassword: write_pass-- 读库
spring:datasource:read:url: jdbc:mysql://slave-db:3306/order_db_0username: read_userpassword: read_pass
六、🔧 监控与运维
6.1 全链路监控
# 应用监控配置
management:endpoints:web:exposure:include: health,info,metrics,prometheusendpoint:health:show-details: alwaysprobes:enabled: truemetrics:export:prometheus:enabled: true# 自定义业务指标
@Component
public class OrderMetrics {private final MeterRegistry meterRegistry;private final Counter orderCreatedCounter;private final Timer orderProcessTimer;private final Gauge activeOrdersGauge;public OrderMetrics(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;this.orderCreatedCounter = Counter.builder("order.created").description("订单创建数量").register(meterRegistry);this.orderProcessTimer = Timer.builder("order.process.duration").description("订单处理耗时").publishPercentiles(0.5, 0.95, 0.99).register(meterRegistry);}public void recordOrderCreated() {orderCreatedCounter.increment();}
}
6.2 日志追踪
@Aspect
@Component
@Slf4j
public class LoggingAspect {@Around("execution(* com.ebusiness..service..*(..))")public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getSimpleName();long startTime = System.currentTimeMillis();try {log.info("开始执行: {}.{}", className, methodName);Object result = joinPoint.proceed();long duration = System.currentTimeMillis() - startTime;log.info("执行完成: {}.{}, 耗时: {}ms", className, methodName, duration);return result;} catch (Exception e) {log.error("执行失败: {}.{}, 错误: {}", className, methodName, e.getMessage());throw e;}}
}
七、🚀 架构演进总结
7.1 性能数据对比
架构阶段 | QPS | 平均响应时间 | 可用性 | 扩展性 |
---|---|---|---|---|
单体架构 | 500 | 100ms | 99.5% | 差 |
垂直拆分 | 5,000 | 50ms | 99.9% | 中等 |
分布式服务 | 50,000 | 30ms | 99.95% | 良好 |
微服务架构 | 500,000 | 20ms | 99.99% | 优秀 |
7.2 技术债务与演进成本
// 架构演进检查清单
@Component
public class ArchitectureReviewChecklist {/*** 检查是否需要进行架构演进*/public ArchitectureReviewResult reviewCurrentArchitecture(SystemMetrics metrics) {List<String> recommendations = new ArrayList<>();// QPS检查if (metrics.getQps() > 1000 && metrics.getCurrentArchitecture() == Architecture.MONOLITH) {recommendations.add("考虑垂直拆分,QPS已超过单体架构承载能力");}// 响应时间检查if (metrics.getAvgResponseTime() > 100) {recommendations.add("响应时间过长,考虑引入缓存和异步处理");}// 可用性检查if (metrics.getAvailability() < 99.9) {recommendations.add("可用性不足,需要引入容错机制和冗余设计");}return new ArchitectureReviewResult(recommendations, getRecommendedArchitecture(metrics));}private Architecture getRecommendedArchitecture(SystemMetrics metrics) {if (metrics.getQps() < 1000) return Architecture.MONOLITH;if (metrics.getQps() < 10000) return Architecture.VERTICAL_SPLIT;if (metrics.getQps() < 100000) return Architecture.DISTRIBUTED;return Architecture.MICROSERVICES;}
}
💎 总结与最佳实践
架构演进原则
- 渐进式演进:不要一步到位,按需演进
- 数据驱动决策:基于性能指标决定演进时机
- 风险控制:每次演进都要有回滚方案
- 团队能力匹配:架构复杂度与团队能力相适应
技术选型建议
- 初创阶段:单体架构 + 简单缓存
- 成长阶段:服务拆分 + 消息队列
- 成熟阶段:微服务 + 服务网格
- 大规模阶段:云原生 + 多集群
💬 互动话题:你在电商平台架构演进中遇到过哪些挑战?是如何解决的?欢迎在评论区分享经验!
👉 下一篇预告:《高并发秒杀系统设计:从理论到实践》
(点击关注第一时间获取更新通知)
🎁 文末福利
关注+私信回复"电商架构"获取:
- 📚 完整架构演进脑图(PDF版)
- 🛠️ 各阶段配置模板
- 📊 性能压测脚本
- 💻 监控Dashboard配置