数藏项目
DDD目录
- controller job listener-->facade-->(apllication)-->domain-->infrastructure
- controller job listener-->apllication-->domain-->infrastructure
公共组件
- SpringBoot3自定义starter 集成xxl-job
- 利用redis实现滑动窗口限流(发短信)rRateLimiter.tryAcquire()
- 分布式锁的封装 RLock rLock = redissonClient.getLock(lockKey);
- Facade的切面处理类,统一统计进行参数校验及异常捕获,耗时,日志打印
- 异常cotroller异常拦截设计 @ControllerAdvice
用户功能
- 验证码:限流防止重复提交
- 注册:分布式锁,布隆过滤器(防重,InitializingBean 的afterPropertiesSet方法完成初始化),缓存
- 一锁二判三更新解决幂等问题(分布式锁aop拦截器增加@Order(Integer.MIN_VALUE)保证最先执行锁的粒度最大,避免事务先执行锁不住)
商品查询功能
- 通过 @ConditionalOnProperty(name = "spring.elasticsearch.enable", havingValue = "true") 选择注入的类
库存
- 下单预扣减(可售库存-1)存数据库,redis,支付真正扣减(已占库存+1)存数据库
- 库存初始化:创建商品-->缓存到redis
- TCC思想 try commit cacel
订单创建
- 通过gateway过滤未认证用户下单
- 商品详情获取token下单避免重复下单,以及通过treadLocal为后续幂等性校验和对账做铺垫
- 创建订单之前通过责任链模式校验 用户,商品,库存
- 创建订单时生成全局唯一id做分表唯一id:业务码+序列号+分表码
- 通过redis扣减预减库存,SpringEvent做数据库预减库存扣除
- @TransactionalEventListener 在主事务提交之后才执行监听
超时关单
- 查看详情,支付主动关单,事务消息,发送半消息通过监听器执行本地方法(同步调用),本地消息消费成功之后再投递mq,进行远程消费。
- XXL-JOB分片任务->没用MQ(orderId/shardTotal=shardIndex)(where order_id%4=0/1/2/3)实现数据隔离
- 生产消费者消费者模式-BlockingQueue
- 线程池-ForkJoinPool
- 毒丸对象
支付
- 生成支付单号:雪花算法+数据库唯一索引 保证幂等性
- 通过工厂策略模式获取对应支付渠道的支付实现类
- 支付中状态轮训,成功后页面跳转
- 支付成功回调,解签,解密
- 支付回调mock 主子线程传递参数通过阿里ttl(InheritableThreadLocal),线程池也需要ttl线程池
- 通过seata的AT模式保证微服务的同一数据库数据一致性,TCC模式适合redis和mysql的一致性
- 通过查询状态做幂等
- 事务Hook(勾子函数)实现上链(外部接口(失败通过定时任务补偿))的一致性
- 多付退款,创建付款单,异步执行退款,失败交给定时任务重试
- 定时任务上链分页查询通过增加条件>minId(上次结果的最大id)避免跳页
- spring2.6之后不支持循环依赖,增加@Lazy注解在使用的时候才初始化可以解决循环依赖