Authored by foxxy

促销重构

  1 +背景:
  2 +
  3 +
  4 +> 当前系统优惠券发放途径分散各处,维护成本高,且问题较多,无法打开产能,运营效率低下。
  5 +
  6 +营销管理券相关:![Alt text](./QQ截图20160503104732.jpg)
  7 +
  8 +促销活动:![Alt text](./1462349575530.png)
  9 +
  10 +改造点:
  11 +1.新增优惠券,审批完成之后不再生成券号,只定义券的总数,前台发券时去控制发券是数量不超过后台定义的这个总数,并在发券的时候生成对应的券码(不再先生成码,然后再去码的池里面获取没有使用的码)。
  12 +
  13 +2.领取规则和使用规则抽象,两者之间不能混淆。
  14 + `2.1`领取规则主要定义券的可领取时间,和用户相关信息的限定规则,包括黑名单,用户渠道等等。
  15 + `2.2`使用规则主要限定券可用的商品、品牌,订单金额等等。
  16 +
  17 +3.券的使用规则逻辑类聚到促销,不再散落在订单模块。
  18 +
  19 +
  20 +实现细节(除公开券之外):
  21 +
  22 +**发券**
  23 +1、校验用户是否已经领取--->校验券的基本信息--->校验领取规则。
  24 +2、校验领取是否已经超过最大券数,券总数做原子性递减,当为小于或等于0时报错(缓存失效之后回填数据库,将券总数-领取记录总数的值回填到redis),实现可参考计数器RedisCounter。
  25 +3、生成唯一优惠券码,插入到用户的领取记录表中,同时清除<用户id,券id,是否领取>hash结构的key。
  26 +4、发送券领取成功的消息盒子。
  27 +
  28 +**查询用户可用券和不可用的券**
  29 +1、查询出用户所有可用的券(状态正确,在有效期内的)
  30 +2、根据商品,订单金额,用户身份,品牌等条件匹配出可以用的券
  31 +**检查券是否可用**
  32 +1、用户是否有该券,在用户的领取记录里面,先从缓存hash中查询用户id+券ID是否存在,缓存查不到查数据。
  33 +2、验证券本身的基本信息,这里可以直接查询券的信息(后续如果有性能瓶颈,券的基本信息这里可以缓存在redis里面几分钟,暂时不考虑)。
  34 +3、验证券是否已经使用,根据券类型不同做验证(公开券每人只能用一次,且不能超过最大使用次数)。
  35 +4、验证券是否符合这些商品,品牌,分类,身份,订单金额等(使用规则验证)。
  36 +**用券**
  37 +1、用户是否有该券,在用户的领取记录里面,先从缓存hash中查询用户id+券ID是否存在,缓存查不到查数据。
  38 +2、验证券本身的基本信息,这里可以直接查询券的信息(后续如果有性能瓶颈,券的基本信息这里可以缓存在redis里面几分钟,暂时不考虑)。
  39 +3、验证券是否已经使用,根据券类型不同做验证,公开券每人只能用一次,且不能超过最大使用次数。
  40 +4、验证券是否符合这些商品,品牌,分类,身份,订单金额等(使用规则验证)。
  41 +5、 修改券为已经使用。
  42 +**领券中心**
  43 + <li>用户如果没登录只查询券的剩余数量(剩余数量先去缓存查询,缓存key不存在就去数据库中查询,数据库中剩余数量=券总数-券 领取记录数,将查询的这个数量设置到缓存中,缓存时间为1天)。
  44 +
  45 + <li> 用户登录情况下, 用户是否领取用 redis hash结构 <uid,couponid,Y>,如果key不存在,批量根据用户id和券id批量查询数据库,查到就放缓存,缓存时间为1天,如果用户本身没券,在redis中维护<uid,couponid,N>,避免每次都要查询数据库。
  46 +
  47 + <li>用户在领券时清除用户的缓存,同时将券的剩余数减1,这里是原子性的操作。
  48 +
  49 +**客服补券**
  50 + 直接掉前台提供的发券接口给用户发券
  51 +
  52 +
  53 + **公开券**
  54 + 公开券还是要先生成券码,这块的逻辑 单独拎开,因为不涉及发放,这里不涉及缓存,直接操作数据库就好,公开券相对较少
  55 +