vivo 全球商城:优惠券系统架构设计与实践

一:业务背景优惠券是电商常见的营销手段 , 具有灵活的特点 , 既可以作为促销活动的载体 , 也是重要的引流入口 。优惠券系统是vivo商城营销模块中一个重要组成部分 , 早在15年vivo商城还是单体应用时 , 优惠券就是其中核心模块之一 。随着商城的发展及用户量的提升 , 优惠券做了服务拆分 , 成立了独立的优惠券系统 , 提供通用的优惠券服务 。目前 , 优惠券系统覆盖了优惠券的4个核心要点:创、发、用、计 。

  • “创”指优惠券的创建 , 包含各种券规则和使用门槛的配置 。
  • “发”指优惠券的发放 , 优惠券系统提供了多种发放优惠券的方式 , 满足针对不同人群的主动发放和被动发放 。
  • “用”指优惠券的使用 , 包括正向购买商品及反向退款后的优惠券回退 。
  • “计”指优惠券的统计 , 包括优惠券的发放数量、使用数量、使用商品等数据汇总 。
vivo商城优惠券系统除了提供常见的优惠券促销玩法外 , 还以优惠券的形式作为其他一些活动或资产的载体 , 比如手机类商品的保值换新、内购福利、与外部广告商合作发放优惠券等 。
以下为vivo商城优惠券部分场景的展示:
vivo 全球商城:优惠券系统架构设计与实践

文章插图
 
二:系统架构及变迁优惠券最早和商城耦合在一个系统中 。随着vivo商城的不断发展 , 营销活动力度加大 , 优惠券使用场景增多 , 优惠券系统逐渐开始“力不从心” , 暴露了很多问题:
  • 海量优惠券的发放 , 达到优惠券单库、单表存储瓶颈 。
  • 与商城系统的高耦合 , 直接影响了商城整站接口性能 。
  • 优惠券的迭代更新受限于商城的版本安排 。
  • 针对多品类优惠券 , 技术层面没有沉淀通用优惠券能力 。
为了解决以上问题 , 19年优惠券系统进行了系统独立 , 提供通用的优惠券服务 , 独立后的系统架构如下:
vivo 全球商城:优惠券系统架构设计与实践

文章插图
 
优惠券系统独立迁移方案
如何将优惠券从商城系统迁移出来 , 并兼容已对接的业务方和历史数据 , 也是一大技术挑战 。系统迁移有两种方案:停机迁移和不停机迁移 。
我们采用的是不停机迁移方案:
  • 迁移前 , 运营停止与优惠券相关的后台操作 , 避免产生优惠券静态数据 。
静态数据:优惠券后台生成的数据 , 与用户无关 。
动态数据:与用户有关的优惠券数据 , 含用户领取的券、券和订单的关系数据等 。
  • 配置当前数据库开关为单写 , 即优惠券数据写入商城库(旧库) 。
  • 优惠券系统上线 , 通过脚本迁移静态数据 。迁完后 , 验证静态数据迁移准确性 。
  • 配置当前数据库开关为双写 , 即线上数据同时写入商城库和优惠券新库 。此时服务提供的数据源依旧是商城库 。
  • 迁移动态数据 。迁完后 , 验证动态数据迁移准确性 。
  • 切换数据源 , 服务提供的数据源切换到新库 。验证服务是否正确 , 出现问题时 , 切换回商城数据源 。
  • 关闭双写 , 优惠券系统迁移完成 。
迁移后优惠券系统请求拓扑图如下:
vivo 全球商城:优惠券系统架构设计与实践

文章插图
 
三、系统设计3.1 优惠券分库分表
随着优惠券发放量越来越大 , 单表已经达到瓶颈 。为了支撑业务的发展 , 综合考虑 , 对用户优惠券数据进行分库分表 。
关键字:技术选型、分库分表因子
分库分表有成熟的开源方案 , 这里不做过多介绍 。参考之前项目经验 , 采用了公司中间件团队提供的自研框架 。原理是引入自研的MyBatis的插件 , 根据自定义的路由策略计算不同的库表后缀 , 定位至相应的库表 。


推荐阅读