手把手教你做系统设计 | 青训营

83 阅读5分钟

这是我参与[第五届青训营]伴学笔记创作活动的第10天。

课程内容:

  1. 系统设计方法论
  2. 电商秒杀业务介绍
  3. 课程实践
  4. 课程总结

01.系统设计方法论

系统设计的那些问题

  1. 为什么要做系统设计
  • 个人:面试、个人能力提升、拓展技术视野
  • 工作:业务驱动、系统重构、突破和创新
  1. 系统设计的定义是什么
  • 系统:关联的个体、规则运作、组成工作的整体
  • 设计:设想和计划、目的、过程安排

定义:为了达成某个目的,通过个体组成整体的过程。 3. 怎么做系统设计,如何落地一个系统

4S分析法

  • 场景分析:什么系统,需要哪些功能,大多的并发量
  • 存储设计:数据如何组织,sql存储,nosql存储
  • 服务设计:业务功能实现和逻辑整合
  • 可扩展性:解决设计缺陷,提高鲁棒性、扩展性
  1. 系统功能实现之后,如何分析瓶颈并优化
  • 火焰图分析:针对单个实例的分析,cpu的使用、内存的使用,找出代码上的瓶颈
  • 链路追踪:在服务中对同一个请求做追踪,知晓哪个请求做了什么服务以及耗时多少
  • 性能测试:找出整个系统性能的不足
  1. 如何验证系统的可用性和稳定性
  • 链路梳理:核心链路、流量漏斗、强弱依赖
  • 可观测性:链路追踪、核心监控、业务报警
  • 全链路测试:压力测试、负载测试、容量测试
  • 稳定性测试:系统限流、业务兜底、熔断降级
  • 容灾演练:混沌工程、应急 手册、容灾预案

02.电商秒杀业务介绍

电商介绍

  1. 供给测
  2. 消费者侧
  3. 交易环境
  • 商品:具有交易价值和属性的信息载体。
  • SPU:标准的产品单元。
  • SKU:库存保持单元。

秒杀业务的特点

  1. 瞬时流量高
  2. 读多写少
  3. 实时性要求高

秒杀的挑战

  1. 高性能
  2. 资源成本
  3. 反欺诈
  4. 流量管控
  5. 鲁棒性
  6. 扩展性
  7. 防止超卖

1. 场景

功能

  • 秒杀活动发布
  • 秒杀商品详情
  • 秒杀下单

并发

  • 万人参与秒杀
  • QPS 1w+
  • TPS 1k+

2. 存储

三级存储:mysql-redis-localcache

3.服务

子服务

  1. 用户服务
  2. 风控服务
  3. 活动服务
  4. 订单服务

基础组件

  1. ID生成器
  2. 缓存组件
  3. MQ组件
  4. 限流组件

4.扩展

  • 流量隔离
  • CDN
  • 缓存优化
  • 流量管控
  • 数据库扩展
  • MQ扩展
  • Redis扩展
  • 服务水平扩展
  • 服务垂直扩展

系统架构图

image.png

03.课程实践

秒杀流程图

image.png

代码讲解

  • common:定义的基础东西,枚举以及一些常量
  • config:redis的一些配置
  • convertet:数据转换
  • controller:spring boot里面常规的controller
  • dao:数据库操作
  • entity:数据库实体
  • enums:枚举
  • handler:异常处理
  • limit:限流组件
  • lock:分布式侧组件
  • model:一些数据模型
  • mq;生产者与消费者
  • service:业务逻辑层,包括server接口与实现
  • util:基础工具

controller

活动

首先创建一个秒杀活动接口activityimage.pngActivity。image.png商品信息image.png限流组件所用image.png校验开始时间与结束时间,校验失败就抛出异常。image.png请求通过就将请求转换一个model,即业务领域。image.pngconvert是定义在request里的一个方法,传进来一个函数编程function。image.pngcinvertCreateActivityModel转换函数(java内比较优雅的写法-函数式编程),使用builder插件。image.png转换为model后,进行业务操作,即直接创建一个活动CreatePromoActivity。image.pngCreatePromoActivity。image.png把前面传进来的model转换成一个实体HPromoimage.png对应数据库内的活动的表image.png合法性校验:

  • id生创建组件生成活动id,放入数据库,如果写失败则返回失败给端上。

image.png

  • 成功后需要从model取出来本次活动需要秒杀的商品。

image.png

  • 再把spuid取出来放入set里面,set内为空则返回创建失败。

image.png

  • set不为空则转换为list,在数据库内查询该商品。若商品不存在与数据库,则返回错误。

image.png

  • 校验商品状态,如果已经下线则也不合法。

image.png

  • 过滤掉已经售卖商品。

image.png

扣除库存。successlist是扣除成功的list,遍历promoProducts。image.pngdecreaseStock。image.png其中调用的hSkudao来扣减库存image.pngdecreaseStock的sql语句。条件是防止超卖,已有库存大于扣减的库存。image.png扣减库存成功后,缓存至generatePromoteStockey。image.png给一个参数k代表秒杀商品库存,缓存预热思想。image.png校验successlist是不是空,空则错误;非空后,批量插入。image.png

活动详情

前端有一个秒杀会场。image.png简单校验image.png商品详情缓存image.pngk的处理。image.png从缓存获取k,若获取失败,则在数据库寻找;若仍为空,则校验活动状态。image.png获取详情的业务逻辑image.png获取活动商品image.png校验spuimage.png获取skuimage.png

下单 登录界面与风控校验image.png首先下单请求转换为一个modelimage.png从秒杀商品sku中构建库存image.png问题:get decrease不是原子,decreaase是原子的,但不可以,回补的库存无法供用户消费。

解决办法image.png前端传过来的价格不置信,所以必须从后端获取image.png支付金额、方式、状态与订单创建(未支付状态),创建时间与更新时间image.png使用mq,优化性能image.pngJSON序列。创建完消息后,直接生产者做send,判断是否send成功。image.png

配置

线程数的配置(800较500合适,通过压测最终确定)image.png日记格式配置image.png数据库配置image.pngredis配置image.png......

组件

限流组件。定义数量与时间。image.png......

分布式锁

解锁(通过脚本)image.pngclose(在抽象父类定义)做自动解锁image.png加锁用的是UUID,使得每个锁不同,防止误删image.png......

ID生成器(雪花算法)

image.png......

课程总结

  1. 服务无状态
  2. 批量写入
  3. 最终一致性