一、背景介绍
1.1 问题
- 搜索结果落地页,按照价格筛选及排序,结果不太准确;
- 用户按照价格筛选后的商品与实际存在的商品不符,可能会缺失部分商品,影响到用户购物体验。
1.2 到手价模块在促销架构中所处的位置
在整体架构中,商品的到手价涉及红包,活动等模块的协同工作。通过将商品售价、红包、活动等因素纳入综合考虑,计算出最终的到手价,为顾客提供良好的购物体验。
二、设计目标
- 体验:用户及时看到商品的最新到手价,提升用户购物体验;
- 实时性:由原来的半小时看到商品的最新到手价,提升到3分钟内。
三、技术方案核心点
3.1 影响因素
影响商品到手价的主要因素:
- 商品,发布或改价;
- 红包,新增/删除或过期;
- 活动/会馆,加入或踢出。
3.2 计算公式
如图所示,商品详情页到手价的优惠项明细可用公式总结如下:
商品的到手价 = 商品原价 - 活动促销金额 - 红包最大优惠金额
四、落地过程及效果
随着业务需求的变化,系统也需要不断地增加新功能或者对现有功能进行改进,通过版本演进,可以逐步引入新的功能模块或优化现有模块,以满足业务的需求。
商品的到手价设计也是遵循这样规则,从开始的v1.0快速开发上线,响应业务;到v2.0,v3.0进行性能优化,升级改造,使用户体验更佳,更及时。
4.1 v1.0流程
v1.0流程一共分为两步:
- 定时任务拉取拉取特定业务线的全量商品,将这批商品全量推送给各个接入方;
- 促销系统提供回查接口,根据商品id等参数,查询商品的到手价;
4.2 v1.0任务及接口
- v1.0任务执行时间长,偶尔还会出现执行失败的情况;而在正常情况下用户大概需要半小时左右才能感知到最新的商品到手价;
- 需要提供额外的单商品及批量商品接口查询到手价,无疑会对系统产生额外的查询压力,随着接入方的增加,接口qps会成比例增加;
4.3 v2.0设计
针对v1.0版本长达半个小时更新一次到手价问题,v2.0解决方案如下:
- 实时处理部分
商品上架/商品改价;
商品加入/踢出活动;
商品加入/踢出会馆;
这部分数据的特点是,上述这些操作是能实时拿到商品的infoId,基于这些商品的infoId,可以立即计算这些商品的到手价并更新出去。
商品发布/改价,加入活动/会馆,踢出活动/会馆;接收这些情况下触发的mq消息,携带商品infoId,直接计算到手价。
- 3min任务,计算特定业务线的全量商品到手价
红包: 新增/更新/删除/过期;
这部分数据的特点是,一是不能很容易能圈出受到影响的这批商品infoIds,二是有些红包的领取和使用范围可能会涉及绝大部分的商品,甚至有些时候大型促销会配置一些全平台红包,影响范围就是全量商品。
综上,结合这两种情况,以及现有的接口及能力实现v2.0;
推送商品的到手价,消息体格式如下,包括商品id,平台类型,到手价:
[
{"infoId":"16606xxxxxxx174465",
"ptType":"10","
realPrice":"638000"}
]
首先在Redis维护全量商品,根据商品上架/下架消息,新增或删除队列中的商品;其次将全量商品保存在10000队列中,每个队列只存一部分商品:
queue1=[infoId...]
queue2=[infoId...]
...
queue9999=[infoId...]
右图显示的是每个队列存储的商品数,队列商品数使其能保持在同一个量级。
多线程并发计算,每个线程只计算自己队列的商品到手价即可;同时增加监控及告警,查看每个线程的计算耗时,右图可以看到大概在120s内各线程计算完成。
注意事项:
- 避免无意义的计算: 将每次变化的红包维护在一个队列中,任务执行时判断是否有红包更新;
- 并发问题: 当任务正在执行中时,此时恰巧商品有变化(改价,加入活动等),将此次商品放入补偿队列中,延迟执行;
综上,结合这两种场景可以做到:
- 某些场景影响商品的到手价(如改价等),携带了商品infoId,能做到实时计算并立即推送最新的到手价;
- 拆分多个商品队列,并发计算;各司其职,每个线程只计算自己队列商品的到手价;
- 降低促销系统压力,接入方只需要监听到手价消息即可。
4.4 v3.0设计
可以看到随着商品数的增加,计算耗时也成比例增加。
解决办法:
- 使用分片,v2.0是将一个大任务,由jvm多线程并发执行各自队列的商品;v3.0则是将这个大任务,由多个分片去执行各自队列中的商品,使其分布式执行来提高任务的执行效率和可靠性;
- 扩展性及稳定性强,随着商品的增多,可以适当增加分片数,降低计算耗时。
5 总结
- 系统扩展性 数据量日渐增大,系统要能做升级扩展;
- 系统稳定性 业务迭代,架构升级,保持系统稳定;
- 完备的监控告警 及时的监控告警,快速发现问题,解决问题;
- 演进原则 早期不过度设计,不同时期采用不同架构,持续迭代。