1,系统设计方法论
系统设计中遇到的问题:
- 为什么要做系统设计
- 系统设计的定义是什么
- 怎么做系统设计,如何落地一个系统设计
- 系统功能实现之后,如何分析瓶颈并优化
- 如何验证系统的可用性和稳定性
为什么要做系统设计:
个人:
- For面试
- 个人能力提升
- 扩展技术视野
工作:
- 业务驱动
- 系统重构
- 突破和创新
如何评估一个系统:
可用性 安全性 扩展性 易用性 可维护性 性能 伸缩性 耦合性
系统设计的定义:
为了达成某种目的,通过个体组成整体的过程
系统:
- 关联的个体
- 规则运作
- 组成工作的整体
设计:
- 设想和计划
- 目的
- 过程安排
如何保证可用性和稳定性:
- 链路梳理:核心链路 流量漏斗 强势依赖
- 可观测性:链路追踪 核心监控 业务报警
- 全链路测试:压力测试 负载测试 容量测试
- 稳定性控制:系统限流 业务兜底 熔断降低
- 容灾演练:混沌工程 应急手册 容灾预案
2. 电商秒杀业务介绍
秒杀业务的特点:
- 瞬时流量高
- 读多写少
- 实时性要求高
秒杀的挑战:
- 资源成本
- 反欺诈
- 高性能
- 防止超卖
- 流量管控
- 扩展性
- 鲁棒性
场景:
秒杀活动发布
秒杀商品详情
秒杀下单
万人参与秒杀
QPS 1w+
TPS 1k+
服务(Service):
- 子服务:用户服务;风控服务;活动服务;订单服务
- 基础组件:ID生成器(生成订单ID——分布式ID生成);缓存组建;MQ组件(保护系统——削峰);限流组件(保护系统)
扩展:
- 流量隔离(与常规流量合理)
- CDN(静态资源缓存,提高效率)
- 缓存优化
- 流量管控(拦截、过滤)
- 数据库扩展
- 服务水平扩展(负载均衡、反向代理)
- MQ扩展(主从架构、多主多从架构)
- Redis扩展
- 服务垂直扩展
系统架构图
3. 课程实践
src/main/java/com/camp/promotion/service/impl/HPromotionServiceImpl.java
public List<CreatePromoProductModel> CreatePromoActivity(CreateActivityModel createActivityModel)
public HPromoProductModel getPromotionProductDetail(Long promoId, Long skuId, Long spuId)
src/main/java/com/camp/promotion/controller/CategoryController.java
public ResponseData<?> testLock() {
// 把锁的创建放在try后,不用写finally了,自动调用close方法
try (RedisDistributedLock lock = new RedisDistributedLock("test_key", 10000)) {
if (lock.tryLock()) {
return ResponseData.Success("ok");
}
} catch (Exception e) {
throw new RuntimeException("lock fail");
}
...
src/main/java/com/camp/promotion/mq/OrderPullConsumer.java
public void doConsumer() throws InterruptedException {
while (isRunning.get()) {
...
executorService.execute(() -> {
try {
// 线程池里做异步消费
processOrder(messageExts);
} catch (Exception e) {
log.error("process order fail, e = ", e);
}
});
...
}
}
@Transactional(rollbackFor = Exception.class)
public void processOrder(List<MessageExt> messageExts) {
...
// 真正从数据库中扣减
int updateStockRes = this.hPromoProductService.decreaseStock(orders.get(0).getActivityId(), orders.get(0).getSkuId(), decreaseCount);
if (updateStockRes < 1) {
log.error("process order fail, size = {}, data = {}", orders.size(), JSON.toJSONString(orders));
this.deadQueue.addAll(orders);
throw new BizException(ResponseEnum.CONSUMER_FAIL);
}
// 批量插入(优化了性能)
int insertRes = this.hOrderService.batchInsert(orders);
if (insertRes < orders.size()) {
log.error("process order fail, size = {}, data = {}", orders.size(), JSON.toJSONString(orders));
this.deadQueue.addAll(orders);
throw new BizException(ResponseEnum.CONSUMER_FAIL);
}
}