电商业务 写一下订单的提交 以及订单发货相关的
上面这个首先进行pageToken校验,防止网络抖动造成的窗口抖动多次提交,另外不直接从redis获取数据,防止并发问题造成同时请求到下面,使用lua脚本的方式保证原子性同时不损失性能,这里uuid生成订单号,我只是举了一个例子,然后一次遍历每个商铺以及商品id的库存,如下图,分别检查每个商品的库存够不够,这里面用了手动事务的方式,一般的事务不太行。另外卡住页面长时间提交也不行,会给pageTok
·
d首先是创建订单,根据
public OrderPageResponse createOrderPage(List<OderPageRequest> oderPageRequests, String personId) {
//生成 提交订单时 所需要的 唯一的 pageToken. 并且存储到后端的 redis 服务器中
String pageToken = UUID.randomUUID().toString();
redisCommonProcessor.set(personId + pageToken, pageToken, 300);
//运费计算, 需要访一个新的 微服务: 仓库微服务
// Integer freight = wareServiceClient.calculateFreight(oderPageRequests);
Integer freight = 0;
//总价计算
BigDecimal totalPrice = new BigDecimal(0);
for (OderPageRequest oderPageRequest : oderPageRequests) {
totalPrice = totalPrice.add(oderPageRequest.getPrice().multiply(new BigDecimal(oderPageRequest.getCount())));
}
totalPrice = totalPrice.add(new BigDecimal(freight));
return OrderPageResponse.builder()
.pageToken(pageToken)
.freight(freight)
.totalPrice(totalPrice)
.build();
}
订单的信息主要包括 商品id 店铺id 价格 数量 以及城市编码
private Long skuId; private Integer shopId; private BigDecimal price; private Integer count; private String cityCode;
订单提交后 会消耗对应的pageToken防止网络波动造成的多次提交。另外卡住页面长时间提交也不行,会给pageToken一个过期时间,这里面涉及到了价格的计算,上游是一个购物车的实现。
创建完订单之后主要是这个token的信息,拿到这个token
用户提交订单请求信息 用户id (全局上下文获取 header通过网关得到的 订单id后面生成根据日期uuid规则,运费是在创建订单里面计算的,我的代码把这个规则省略了,pageToekn 还有商品列表 包含了购买每个商品的库存
public class OrderSubmitRequest implements Serializable {
//用户相关信息
private String personId;
private String orderId;
private Integer freight;//运费
private String cityCode;//收获地址管理
private String pageToken;
private String orderStatus;
private Date createTime;
//购买商品信息
private List<OrderItemEntity> orderItemEntities;
}
public CommonResponse submitOrder(OrderSubmitRequest orderSubmitRequest) {
String personId = orderSubmitRequest.getPersonId();
String pageToken = orderSubmitRequest.getPageToken();
//并发问题 synchronized不行,分布式锁 性能稍差 redis的一个命令执行 尤其是lua脚本
// if(cachedToken == null || !cachedToken.equals(personId)) {
// return ResponseUtils.failResponse(ResponseCode.BAD_REQUEST.getCode(), null,"expired");
// }
// redisCommonProcessor.remove(personId + pageToken);
String luaScript = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
Long validate = redisCommonProcessor.runLuaScripts(luaScript, pageToken, personId + pageToken);
if(validate == 0) {
return ResponseUtils.failResponse(ResponseCode.BAD_REQUEST.getCode(), null,"expired");
}
//假设是雪花算法
UUID uuid = UUID.randomUUID();
String orderId = uuid.toString();
orderSubmitRequest.setOrderId(orderId);
List<OrderWareLockResponse> orderWareLockResponses = wareServiceClient.lockWare(orderSubmitRequest);
Map<Boolean, List<OrderWareLockResponse>> wareLockMap = orderWareLockResponses.stream().collect(Collectors.groupingBy(OrderWareLockResponse::isLocked));
if(wareLockMap.get(false) != null) {
return ResponseUtils.failResponse(ResponseCode.BAD_REQUEST.getCode(), orderWareLockResponses,"your page is wrong");
}
//存入redis,支付时的查询,减少db依赖
createOrderInfo(orderSubmitRequest);
redisCommonProcessor.set(orderId, JSON.toJSONString(orderSubmitRequest), 1200);
//支付信息
rabbitTemplate.convertAndSend(ConstantUtils.ORDER_EXCHANGE,ConstantUtils.ORDER_CONFIRM_QUEUE,orderSubmitRequest);
//订单信息
rabbitTemplate.convertAndSend(ConstantUtils.ORDER_EXCHANGE,ConstantUtils.ORDER_DATA_QUEUE,orderSubmitRequest);
return ResponseUtils.okResponse(orderSubmitRequest);
}
上面这个首先进行pageToken校验,防止网络抖动造成的窗口抖动多次提交,另外不直接从redis获取数据,防止并发问题造成同时请求到下面,使用lua脚本的方式保证原子性同时不损失性能,这里uuid生成订单号,我只是举了一个例子,然后一次遍历每个商铺以及商品id的库存,如下图,分别检查每个商品的库存够不够,这里面用了手动事务的方式,一般的事务不太行。最后把订单信息分别存reids以及支付信息队列和订单信息队列,后面根据我的学习仅需更新
更多推荐




所有评论(0)