企业级分布式优惠券项目-业务思想及整体架构

这一章将完整介绍优惠券系统的业务思想,包含三个功能微服务:模板微服务,分发微服务和结算微服务。之后对存储方面的设计进行了介绍,包含MySQL和Redis缓存的设计思想。最后,对系统的整体架构进行了介绍,优惠券系统的架构分为两类:SpringCloud组件架构和功能微服务架构。对这个项目技术细节的同学可以留言与我讨论

优惠券系统业务思想

模板微服务

  1. 先由运营人员创建优惠券模板,之后再去生成对应数量的优惠券,最后用户才可以领取优惠券。这个模块的核心功能就是围绕优惠券模板的。运营人员设定好条件(名称、logo、分类、产品线、数量、规则等等),后台异步创建优惠券模板,之所以是异步过程,是因为创建优惠券模板的过程是比较耗时的,HTTP接口不返回是一种不好的用户体验。

生成优惠券需要考虑两个方面:

  • 不可以重复
  • 有一定的识别性

最终把优惠券码设计为18位,由三个部分组成:

  • 前四位:产品线和类型
  • 中间六位:日期随机
  • 后八位:0-9的随机数

业务思想如图所示:

  1. 模板创建的一个关键步骤是异步生成对应的优惠券码,并保存到Redis中。需要注意的是:
  • 提高异步线程池的效率,这里我们自定义线程池实现
  • 静态单实例生成优惠券码

业务思想如图所示:

  1. 运营人员创建的优惠券模板不可能是一直有效的(模板一旦过期,它所对应的优惠券就不能再分发给用户。但是,已经分发给用户的,可以是不过期的),所以,需要一个过期机制能让过期的优惠券不返回给用户展示。这里设计两种策略:
  • 实现一个定时任务,如每小时运行一次,清理过期的优惠券模板
  • 获取优惠券模板时,判断是否过期。之所以这样做,是因为定时任务有间隔的延迟,不能保证实时过期

分发微服务(用户相关)

  1. 分发模块主要涉及四个核心的功能点。
  • 对接用户中心系统,校验用户相关信息,是否非法用户等
  • 定义用户优惠券(注意与优惠券模板区分开,这里是实际用户领导的优惠券)三种状态:可用、已使用、过期
  • 用户相关优惠券数据存入Redis中,可提升展示优惠券速度
  • 展示用户优惠券时,要校验是否过期

业务思想如图:

  1. 根据用户id查找当前可领取的优惠券模板
  • 优惠券模板是一个独立的服务,所以,分发模块需要rpc调用去获取模板数据。但访问微服务存在不确定性,所以要有熔断兜底(hystrix)的策略
  • 模板微服务中获取到的优惠券模板,不一定是可取的,需要去比对优惠券模板的相关限制。例如,有一张优惠券模板A,限制用户只能领取一张可用。那么如果之前已经领取过了,即使是可用状态,也不能再领取了。

业务思想如图:

  1. 用户领取优惠券
  • 直接从Redis中获取优惠券码
  • 通过了验证,即优惠券模板是可以领取的,且成功领取到了优惠券码,就可以将优惠券写入MySQL和Redis中了

业务思想如图:

  1. 结算(核销)优惠券
  • 无论是结算还是核销,都需要对前端/客户端传递的参数值进行校验,判断当前用户想要使用的优惠券是否是合法的,合法的标准是判断属于当前用户且优惠券的状态是可用的
  • 由于分发微服务直接面向用户,而结算这样的功能实际只与优惠券相关,更细致的说,是只与优惠券模板定义的规则相关。所以,结算功能不放在分发微服务中,而是由优惠券系统的第三个功能微服务负责,即结算微服务
  • 结算和核销是两个不同的概念。结算是计算利用优惠券可以优惠的金额,但并不是使用。这种场景发生在我们付款之前,优惠券并未使用,但是,也会显示使用优惠券之后优惠的金额和实际需要结算的金额。而核销则是使用优惠券。对于核销这种情况,需要把数据回写到数据库中。

业务思想如下:

结算微服务

只提供一个功能:根据优惠券类型结算优惠券

  • 在涉及优惠券时,会对优惠券设置不同的分类,如:满减类、折扣类。大家也可以自行扩展更多的类
  • 优惠券的种类不同,就会有不同的结算方式,或者说是结算的算法。例如,满减券是根据满多少金额减去多少金额,而折扣券是直接打一定的折扣等。另外,更复杂的情况是优惠券之间可以组合。例如满减和折扣组合,先去满减,再打一定的折扣。结算的算法可以使用策略设计模式来提高工程的可扩展性

业务思想如图:

存储设计

MySQL表设计

一共两张MySQL表:

  • 优惠券模板表:优惠券模板是与用户无关的,是对一类优惠券的描述。运营人员通过设定模板,来描述优惠券的各种信息

  • 用户优惠券表:记录用户和优惠券之间的关联关系。

Redis缓存设计

对于缓存,也是有两类,且都是使用Redis来实现

  • 优惠券码缓存Key是需要有意义的,即最好能够根据Key来识别它对应的是什么数据。券码是需要一直保持再系统中,等待分发(即等待用户的领取),所以,并不设置过期时间。

总结下来,为了保证优惠券码的Key不冲突,以前缀+主键的形式构成;且使用list类型来保存券码

  • 用户优惠券信息缓存由于优惠券分为3类,为了更加高效的检索,这里也会使用到三个缓存去实现。且由于每一类优惠券都可能是很多个,所以使用Redis的Hash类型由于用户数据量比较大,且在MySQL中有完整的用户信息。所以,不在Redis中长时间保留用户优惠券信息。需要设置一个过期时间。

用户优惠券信息缓存的key是前缀+用户id的形式;value是hash类型,hash的key是优惠券id,hash的value是优惠券信息

架构设计

  1. SpringCloud微服务组件架构

这里主要是两个组件:Eureka和Zuul,客户端的请求入口是Zuul,也是整个系统的网关服务。网关服务的最核心功能是能够根据请求做分发。把不同的请求分发到对应的微服务上。Eureka Server是整个系统的注册中心,是SpringCloud服务治理的基础。不论网关还是功能微服务,都需要把自己注册到Eureka Server上。各自在需要系统元信息的时候,再去询问Eureka Server去主动获取。

  1. 功能微服务架构设计

结算服务是比较独立的,目前只是我们的优惠券分发服务在做结算时会使用到。但是,对于结算,可以设计的更加通用,不只是优惠券的结算,还可以扩展成商品的结算等等。所以,在实现上,会把结算服务单独的作为一个微服务。模板服务和结算服务不依赖于其他的服务,而分发服务则会依赖他们两个。实现上,需要考虑调用方式和熔断降级策略。

全部评论

相关推荐

04-30 21:35
已编辑
长安大学 C++
晓沐咕咕咕:评论区没被女朋友好好对待过的计小将可真多。觉得可惜可以理解,毕竟一线大厂sp。但是骂楼主糊涂的大可不必,说什么会被社会毒打更是丢人。女朋友体制内生活有保障,读研女朋友还供着,都准备订婚了人家两情相悦,二线本地以后两口子日子美滋滋,哪轮到你一个一线城市房子都买不起的996清高计小将在这说人家傻😅
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
11
47
分享

创作者周榜

更多
牛客网
牛客企业服务