Java工程实践案例分析:构建高可用的电商系统
【摘要】 Java工程实践案例分析:构建高可用的电商系统 一、项目背景与核心指标指标目标备注日均订单1000 万峰值 5 倍突发可用性99.99 %全年不可用 < 53 minP99 下单延迟< 200 ms含风控与库存扣减数据一致性最终一致TCC + 消息表模式 二、整体技术架构┌──────────────┐ 静态化 ┌──────────────┐ 动态渲染 ┌────────────...
Java工程实践案例分析:构建高可用的电商系统
一、项目背景与核心指标
指标 | 目标 | 备注 |
---|---|---|
日均订单 | 1000 万 | 峰值 5 倍突发 |
可用性 | 99.99 % | 全年不可用 < 53 min |
P99 下单延迟 | < 200 ms | 含风控与库存扣减 |
数据一致性 | 最终一致 | TCC + 消息表模式 |
二、整体技术架构
┌──────────────┐ 静态化 ┌──────────────┐ 动态渲染 ┌──────────────┐
│ CDN/Edge │────────▶│ BFF(Gateway)│────────▶│ 业务微服务 │
└──────────────┘ └──────────────┘ │ (SpringBoot) │
└──────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Nacos │────────▶│ Sentinel │────────▶│ Seata │
│ 配置/注册 │ │ 限流熔断 │ │ 分布式事务 │
└──────────────┘ └──────────────┘ └──────────────┘
三、领域模型与代码结构(DDD 六边形)
mall/
├── mall-portal-api // 用户侧接口
├── mall-inventory-api // 库存接口
├── mall-order-service // 订单聚合根
├── mall-payment-service
└── mall-shared-domain // 通用值对象
3.1 订单聚合根示例
package com.mall.order.domain.model;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name = "t_order")
public class Order {
@Id
private Long id;
@Embedded
private UserId buyerId;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
private List<OrderItem> items;
@Enumerated(EnumType.STRING)
private OrderStatus status;
public void confirm() {
if (status != OrderStatus.PENDING) {
throw new IllegalStateException("Order is not pending");
}
this.status = OrderStatus.CONFIRMED;
registerEvent(new OrderConfirmedEvent(this.id));
}
}
四、高可用库存扣减:TCC + 消息表
4.1 库存 Try 接口
@LocalTCC
public interface InventoryTccService {
@TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel")
boolean tryDeduct(@BusinessActionContextParameter(paramName = "skuId") Long skuId,
@BusinessActionContextParameter(paramName = "qty") Integer qty);
boolean confirm(BusinessActionContext ctx);
boolean cancel(BusinessActionContext ctx);
}
4.2 实现类:基于版本号乐观锁
@Service
public class InventoryTccServiceImpl implements InventoryTccService {
@Autowired
private JdbcTemplate jdbc;
@Override
public boolean tryDeduct(Long skuId, Integer qty) {
int updated = jdbc.update(
"update t_inventory set freeze_qty = freeze_qty + ? where sku_id = ? and available_qty >= ?",
qty, skuId, qty
);
return updated == 1;
}
@Override
public boolean confirm(BusinessActionContext ctx) {
Long skuId = (Long) ctx.getActionContext("skuId");
Integer qty = (Integer) ctx.getActionContext("qty");
jdbc.update(
"update t_inventory set available_qty = available_qty - ?, freeze_qty = freeze_qty - ? where sku_id = ?",
qty, qty, skuId
);
return true;
}
@Override
public boolean cancel(BusinessActionContext ctx) {
Long skuId = (Long) ctx.getActionContext("skuId");
Integer qty = (Integer) ctx.getActionContext("qty");
jdbc.update(
"update t_inventory set freeze_qty = freeze_qty - ? where sku_id = ?",
qty, skuId
);
return true;
}
}
4.3 消息表保证最终一致
CREATE TABLE t_inventory_msg (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
sku_id BIGINT NOT NULL,
qty INT NOT NULL,
status ENUM('NEW','DONE','FAIL') DEFAULT 'NEW',
create_time DATETIME NOT NULL,
UNIQUE KEY uniq_sku (sku_id, qty, create_time)
);
通过定时任务扫描 status='NEW'
行,幂等发送到 MQ,消费者更新缓存。
五、读写分离 + 分库分表:ShardingSphere
5.1 配置(YAML)
dataSources:
ds_0:
url: jdbc:mysql://10.0.0.11:3306/mall_order_0
ds_1:
url: jdbc:mysql://10.0.0.12:3306/mall_order_1
rules:
- !SHARDING
tables:
t_order:
actualDataNodes: ds_${0..1}.t_order_${0..7}
tableStrategy:
standard:
shardingColumn: buyer_id
shardingAlgorithmName: order_inline
keyGenerateStrategy:
column: id
keyGeneratorName: snowflake
shardingAlgorithms:
order_inline:
type: INLINE
props:
algorithm-expression: t_order_${buyer_id % 8}
5.2 读写分离 Hint
HintManager hint = HintManager.getInstance();
hint.setWriteRouteOnly(); // 强制主库
// 业务代码...
hint.close();
六、Sentinel 限流与热点参数防护
6.1 引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
6.2 热点参数限流规则(动态配置)
spring:
cloud:
sentinel:
datasource:
hotspot:
nacos:
server-addr: nacos:8848
data-id: hotspot-order
rule-type: param-flow
6.3 代码埋点
@GetMapping("/order/{skuId}")
@SentinelResource(value = "createOrder",
blockHandler = "createOrderBlock",
fallback = "createOrderFallback")
public ApiResp<OrderDTO> createOrder(@PathVariable Long skuId,
@RequestParam(defaultValue = "1") Integer qty) {
return orderAppService.create(skuId, qty);
}
public ApiResp<OrderDTO> createOrderBlock(Long skuId, Integer qty, BlockException e) {
return ApiResp.fail("系统繁忙,请稍后重试");
}
七、灰度发布:基于 Nacos 标签路由
7.1 服务元数据
spring:
cloud:
nacos:
discovery:
metadata:
version: v2025.07.canary
7.2 路由规则(YAML DSL)
strategy: V
routes:
- predicates:
- Headers=canary,true
weight: 100
tags:
version: v2025.07.canary
八、监控与故障演练
8.1 指标采集
- JVM : Micrometer → Prometheus → Grafana
- 业务 : 订单创建 QPS、库存扣减失败率
- 中间件 : Seata 事务回滚次数、Sentinel 限流 QPS
8.2 Chaos-Blade 演练脚本
# 网络延迟 200 ms
blade create network delay --time 200 --interface eth0 --timeout 60
# MySQL 主库 CPU 满载
blade create cpu fullload --cpu-percent 100 --timeout 120
九、关键代码仓库
模块 | GitHub 地址 | 备注 |
---|---|---|
mall-order-service | github.com/mall/order | TCC+ShardingSphere |
mall-inventory-service | github.com/mall/inventory | 乐观锁+消息表 |
mall-infra | github.com/mall/infra | Sentinel/Nacos 配置 |
十、结语
高可用不是“加机器”,而是可验证的故障容错设计。
通过 DDD 限界上下文隔离、TCC 保证库存强一致、ShardingSphere 水平扩展、Sentinel 动态防护,以及灰度发布降低爆炸半径,电商系统才能在 1000 万级订单场景下存活。
下一步,我们将引入 Serverless 弹性伸缩 与 异步事件总线 Pulsar,持续演进。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)