项目
博客
文档
归档
资源链接
关于我
项目
博客
文档
归档
资源链接
关于我
23| 流量漏斗模型驱动解决方案
2024-08-09
·
·
原创
·
·
本文共 293个字,预计阅读需要 1分钟。
### 优惠券拉新发放接口设计和思路 - ⽤户注册->发放优惠券: - `RPC调⽤`:分布事务 - `消息队列`:可靠性投递、幂等操作 说下两种⽅式的优缺点和选择: - `rpc实时性⾼`,`强⼀致性`的场景下⽐消息队列优秀。 - `上下游系统`处理能⼒存在差距的时候`消息队列`可以很好的缓冲 - 引⼊消息队列,系统`可⽤性降低`,假如队列宕机则系统就不能正常运行 - 引⼊消息队列,系统`复杂性增加`,考虑多⽅⾯的问题,⽐如⼀致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输等 ### 流量漏斗模型 互联⽹产品其本身就是⼀个虚拟的漏⽃,⽤户的⾏为路径有很多,举个淘宝、JD这电商例⼦。 ⾸⻚->查看商品->添加购物⻋->注册->登录->下单->⽀付->确认收货 每⼀步都有折损。 就是找事给我们做,不断提⾼每⼀步的转换率,降低每步的折损 - 调整布局、⽤户体验、缩短链路等 - 不定期的短信邮箱推送提醒、标题党等 - 拼团、优惠券、积分等等需求就是这样来的 作为技术Leader的你,为什么要⽤? - 我们要有个做⼀个精益创业的思维 ”⼩步快跑,快速试错“ - 把简单的事情想复杂,把复杂的事情做简单 - 简历编写的时候,给些⼤⼚的产品数据参考(⾮现象级爆款) - ⽇活1千万的⽤户,总⽤户量1 - 2 亿,⽇新增5~10万 - ⽇活1百万的⽤户,总⽤户量1 - 2 千万,⽇新增1~2万 - ⽇活5千,总⽤户量60 -803万之间,⽇新增1K~3K 通过前⾯流量漏⽃分析其实多数公司⾥⾯,注册的量级不⾼(排除⼤量买量和现象级爆款) - 直接使⽤rpc调⽤即可,不引⼊消息队列 - 这⾥会涉及到分布式事务问题,思考,假如发放优惠券失败应该怎么办? - 两个微服务同时进⾏回滚? - 不给注册的账号登录了吗? 你这样会丢掉⼯作的,任何⽅式都不能⼀⼑切,⼀定要思考下具体场景具体⽽定 `假如RPC⽅式调⽤-优惠券发放失败,记录⽇志就⾏,可以⼈⼯补发或者定时任务补发` - 前期不⽤引⼊相关的微服务组件 ### 新用户注册发放优惠券接口 请求对象 ```java @ApiModel(value = "新用户注册发放优惠卷对象", description = "新用户注册发放优惠卷请求对象") @Data public class NewUserCouponRequest { @ApiModelProperty(value = "用户Id", example = "19") @JsonProperty("user_id") private long userId; @ApiModelProperty(value = "名称", example = "二当家") @JsonProperty("name") private String name; } ``` controller层 ```java /** * 新用户注册发放优惠券接口 * @return */ @ApiOperation("RPC-新用户注册接口") @PostMapping("/new_user_coupon") public JsonData addNewUserCoupon( @ApiParam("用户对象") @RequestBody NewUserCouponRequest newUserCouponRequest ){ JsonData jsonData = couponService.initNewUserCoupon(newUserCouponRequest); return jsonData; } ``` service层 ```java /** * 用户微服务调用的时候,没传递token * * 本地直接调用发放优惠券的方法,需要构造一个登录用户存储在threadlocal * * @param newUserCouponRequest * @return */ @Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED) @Override public JsonData initNewUserCoupon(NewUserCouponRequest newUserCouponRequest) { LoginUser loginUser = new LoginUser(); loginUser.setId(newUserCouponRequest.getUserId()); loginUser.setName(newUserCouponRequest.getName()); LoginInterceptor.threadLocal.set(loginUser); //查询新用户有哪些优惠券 List
couponList = baseMapper.selectList( Wrappers.
lambdaQuery().eq(CouponEntity::getCategory, CouponCategoryEnum.NEW_USER.name())); for(CouponEntity coupon : couponList){ //幂等操作,调用需要加锁 this.addCoupon(coupon.getId(),CouponCategoryEnum.NEW_USER); } return JsonData.buildSuccess(); } ```