商城项目要点整理
2023-02-15 10:09:40 0 举报
AI智能生成
畅购商城B2C模式要点整理
作者其他创作
大纲/内容
电商技术特点
技术新
技术范围广
分布式
高并发、集群、负载均衡、高可用
海量数据
业务复杂
系统安全
主要电商模式
B2B
交易双方都是商家
比如:阿里巴巴、慧聪网
C2C
交易双方都是个人
比如:咸鱼、瓜子二手车
B2C
商家对客户
比如:唯品会、乐蜂网
C2B
客户对商家
比如:海尔商城、尚品宅配
O2O
线上对线下
比如:美团、饿了么
F2C
工厂对客户
厂商到消费者
B2B2C
供应商对企业对客户
比如:京东、天猫
项目介绍
项目描述
技术描述
微服务架构
SpringCloud 全家桶
Gateway
过滤
路由
限流
令牌桶限流
Hystrix
微服务保护
默认线程池隔离
通过feign远程调用时为了避免令牌无法传递过去
需要将隔离策略换成信号量隔离
Feign
远程调用
Nacos
注册中心与配置中心
SpringSecurity OAuth2.0
JWT token增强
授权微服务
Seata
分布式事务
ElasticSearch
海量数据实时搜索
Mysql
数据存储
Canal
Mysql数据同步
Redis
数据缓存
OpenResty
处理最外层的大量并发
结合Redis做多级缓存
LVS+Keepalive+Nginx
解决单点故障问题
七层负载均衡
RabbitMQ
异步
削峰
解耦
MinIO
对象存储
Freemarker
模板引擎
商品静态页生成
XXL-Job
分布式任务调度
Jenkins
持续集成
服务拆分
业务微服务
商品微服务
广告微服务
订单微服务
权限微服务
用户微服务
秒杀微服务
管理员后台微服务
公共组件微服务
Seata分布式微服务
OAuth2.0授权微服务
RabbitMQ微服务
Canal微服务
支付微服务
技术架构
涉及技术
系统架构
系统架构图
核心业务
购物车
未登录也可以使用购物车
未登录前,存储在cookie(或者localStage里面)里面,登录后存储在redis里面
必须登录才能使用购物车
存储在redis里面,使用hash类型
订单
流程描述
选择收货地址,选择支付方式后,才能提交订单。
提交订单后会创建订单,并从购物车中删除商品(如果是从购物车中进行结算的话)
创建订单后会生成两张表,一张订单表,一张订单明细表
在这个阶段要注意可能会产生超卖问题
问题描述
每次下单前,都要有个价格校验,不能使用购物车里面的价格,要使用当前商品的价格和购物车价格进行比较
如果一致就可以进行下单,如果不一致,需要修改价格才行
这个逻辑必须得有,因为我们购物车的数据不会一直去请求服务端,
在购物车没发生变化的情况下,会缓存在本地
在购物车没发生变化的情况下,会缓存在本地
因此缓存的商品价格可能是很久以前的价格了
支付
流程图
流程描述
用户请求经过网关转发到订单微服务(下单操作)
订单微服务创建订单,订单会存储在数据库中;
并将一条消息(订单id等即可)发送到延迟队列中(延迟30分钟)
并将一条消息(订单id等即可)发送到延迟队列中(延迟30分钟)
同时订单微服务会监听延迟队列,30分钟后会消费到这条消息,
我们和查询数据库进行比较,如果这单还未完成支付,
那么订单微服务就会执行这条消息,回滚这条订单响应的所有操作
我们和查询数据库进行比较,如果这单还未完成支付,
那么订单微服务就会执行这条消息,回滚这条订单响应的所有操作
但是回滚前,一定要先把这个订单关闭掉(也可以理解成关闭掉支付)。
关闭掉后就无法进行支付了,避免再回滚操作的同时,有人进行了支付操作
关闭掉后就无法进行支付了,避免再回滚操作的同时,有人进行了支付操作
访问支付微服务(需要携带订单编号)
支付微服务访问微信服务(通过http请求的方式去请求微信系统)
微信服务会根据订单账号生成一个预付费记录
预付费记录会把一个预付款的地址给到我们的系统(即预付费记录中包含有预付款的地址)
拿到预付款的地址后,以这个地址为内容,去创建生成二维码
用户就可以扫码进行支付
扫码支付
扫码后与微信服务器进行一个授权认证
微信服务会检查这个链接是否有效
有效的话,会弹出一个授权的界面
授权成功后就会调微信的服务开始进行交易
如果用户名密码正确就能完成交易
交易成功后,会通知给用户
同时,会调用我们的一个notifyUrl
(一般是支付微服务的一个地址,我们进行预付费请求的时候会携带该地址)
(一般是支付微服务的一个地址,我们进行预付费请求的时候会携带该地址)
支付系统收到通知后,会发送消息给mq
订单系统监听mq,消费消息,更新订单的状态
(支付成功,或者支付失败)
(支付成功,或者支付失败)
秒杀
流程图
流程描述
秒杀的商品录入到数据库中(mysql)
mysql定时同步到redis中
用户的请求打到OpenResty,
通过OpenResty去请求秒杀的频道和商品详情页
通过OpenResty去请求秒杀的频道和商品详情页
去redis中请求秒杀列表页的数据
如果用户点击了某个具体的商品,那么商品详情页的数据页也是从redis中读取
用户进行了下单
需要检验是否有库存,通过OpenResty检验库存,
库存数据在redis中(通过OpenResty将大量无效的请求过滤掉,
即这部分不合法的请求压根就不会进入到我们的微服务系统中去)
库存数据在redis中(通过OpenResty将大量无效的请求过滤掉,
即这部分不合法的请求压根就不会进入到我们的微服务系统中去)
如果库存充足,则验证用户有没有登录
未登录,进行OAuth2.0授权登录
进入秒杀微服务
不采用传统的抢单模式,传统抢单模式,需要进行一系列的校验,
校验通过后才有资格进行抢单,但是这一些校验非常耗时,
因此在大量请求下很容易出问题(所有请求都会阻塞在这里,服务会被搞挂掉)。
一系列的校验包括:
校验通过后才有资格进行抢单,但是这一些校验非常耗时,
因此在大量请求下很容易出问题(所有请求都会阻塞在这里,服务会被搞挂掉)。
一系列的校验包括:
账号是否异常
24小时内是否购买过该商品
是否存在未支付的秒杀商品
该秒杀商品是否还有库存
该秒杀商品抢购人数是否达到上线
使用队列模式,将抢单信息(包含订单信息、商品信息、用户信息)存储到redis的队列中
(需要有用户排队信息队列用来标识用户是否重复排队,需要有用户排队状态队列,用于检测用户的排队状态 ),
避免服务器一口气处理所有请求,达到削峰减流的一个效果,避免服务器被搞挂
(需要有用户排队信息队列用来标识用户是否重复排队,需要有用户排队状态队列,用于检测用户的排队状态 ),
避免服务器一口气处理所有请求,达到削峰减流的一个效果,避免服务器被搞挂
进入redis队列后,提示用户进入了排队当中
同时后台利用多线程进行一个下单操作(多线程抢单)
多线程下单也要检查传统抢单模式中信息,只有校验通过后才有资格抢单
同时利用redis中的原子操作去实现库存的递减
下单成功后会同步更新用户排队的状态
用户就抢单成功进入支付环节了,用户支付成功后,将redis中的订单信息删除掉
同时会插入一条延时消息到延迟队列中(包含订单信息、商品信息、用户信息)
当延迟时间到了后,取出来查看下redis中是否有这个订单,
如果有(如果支付完成了,redis中的订单数据就被移除了),
表示还未完成支付,那么进行取消订单的操作(关闭支付、清理订单、回滚库存)
如果有(如果支付完成了,redis中的订单数据就被移除了),
表示还未完成支付,那么进行取消订单的操作(关闭支付、清理订单、回滚库存)
常见问题
如果用户支付成功了,但是微信服务没有把支付状态同步过来(比如网络原因),
在你的系统没有收到支付状态的情况下,你们系统怎么办?是怎么处理的?
在你的系统没有收到支付状态的情况下,你们系统怎么办?是怎么处理的?
腾讯的微信支付提供了一个支付状态查询接口,如果支付系统没有收到支付状态的回调,
我们可以在订单系统中主动调用支付状态查询接口,主动去进行查询(只需要根据本地订单号去查询即可)。
我们可以在订单系统中主动调用支付状态查询接口,主动去进行查询(只需要根据本地订单号去查询即可)。
或者可以在用户查看订单的时候进行判断,如果订单的状态是支付中并且超时很久了的话,就可以调用下支付状态查询接口
如何解决秒杀中重复排队问题?
利用redis的特性,给每个排队的用户整一个排队标识,默认值为1。
如果值大于1,即表示重复排队了。(给一个key做+1的操作,key不存在,则生成key,并将值设为1)
如何解决并发削峰问题?
利用redis的队列来实现削峰填谷
如何防止秒杀超卖问题?
给每个商品的个数存一个队列,比如商品A有五个,那么GoodsList:A(key) 1,1,1,1,1 给它存五个元素进去
卖的时候,每次从队列里面拿一个,如果能拿到表示当前还有库存
如何实现超时订单回滚问题?
定时扫表
性能差
Java内存延迟队列
优点
基于jvm内存
效率高
任务触发延迟低
缺点
存在jvm内存中,服务重启数据丢失
依赖代码硬编码,无法进行集群扩充
依赖jvm内存,如果订单过多,会出现oom问题
MQ实现
方案
利用RabbitMQ延迟队列来实现, 30分钟后执行任务,
同时判断redis有没有订单信息存在,有的话,表示没有进行支付
同时判断redis有没有订单信息存在,有的话,表示没有进行支付
我们就可以关闭支付,关闭订单,回滚库存
优点
缺点
Redis实现
List + Zset实现
被动取消
在每次用户查询订单时
判断订单时间,超时则取消
优点
缺点
重复支付问题
支付时序图
可能原因
解决方法
数据修复
问题处理
异常订单问题
支付但未开单
对账一般一天一次
因此会存在延迟
未支付但已开单
回调延迟问题
支付路由问题
支付中心对接多个支付路由
价格分摊问题
如何避免财务无法平账问题
退单处理问题
保障用户权益
限时购买商品自动下架问题
和超时订单回滚一致
库存管理问题
乐观锁
悲观锁
直接数据库操作的话,数据库会扛不住
因此一般用redis缓存,然后做decr处理
正常下单后,在使用mq异步更新到数据库
双11可能存在的问题
内部瓶颈
外部服务
数据库调优
开启慢查询日志
执行计划分析
缓存优化
热点数据预热
细粒度设计
可用性
收藏
收藏
0 条评论
下一页