vivo商城促销系统架构设计与实践-概览篇
mhr18 2024-12-09 12:09 28 浏览 0 评论
一、前言
随着商城业务渠道不断扩展,促销玩法不断增多,原商城v2.0架构已经无法满足不断增加的活动玩法,需要进行促销系统的独立建设,与商城解耦,提供纯粹的商城营销活动玩法支撑能力。
我们将分系列来介绍vivo商城促销系统建设的过程中遇到的问题和解决方案,分享架构设计经验。
二、系统框架
2.1 业务梳理
在介绍业务架构前我们先简单了解下vivo商城促销系统业务能力建设历程,对现促销能力进行梳理回顾。在商城v2.0中促销功能存在以下问题:
1. 促销模型不够抽象,维护混乱,没有独立的活动库存;
2. 混乱的活动共融互斥关系管理,缺乏统一的促销计价能力。
商城核心交易链路中商详页、购物车、下单这三块关于计价逻辑是分开独立维护的,没有统一,如下图所示。显然随着促销优惠的增加或者玩法的变动,商城侧业务重复开发量会显著加大。
(图2-1. 促销计价统一前)
3. 促销性能无法满足活动量级,往往会影响商城主站的性能。
因与商城系统耦合,无法提供针对性的性能优化,造成系统无法支撑越来越频繁的大流量场景下大促活动。
基于这些痛点问题,我们一期完成促销系统的独立,与商城解耦,搭建出促销系统核心能力:
优惠活动管理
对所有优惠活动抽象出统一的优惠模型和配置管理界面,提供活动编辑、修改、查询及数据统计等功能。并独立出统一的活动库存管理,便于活动资源的统一把控。
促销计价
基于高度灵活、抽象化的计价引擎能力,通过定义分层计价的促销计价模型,制定统一的优惠叠加规则与计价流程,实现vivo商城促销计价能力的建设。推动完成vivo商城所有核心链路接入促销计价,实现全链路优惠价格计算的统一,如下图:
(图2-2. 促销计价统一后)
随着一期促销系统核心能力的完成,极大的满足了业务需要,各类优惠玩法随之增多。但伴随而来的就是各种运营痛点:
- 维护的促销活动无法提前点检,检查活动效果是否符合预期;
- 随着优惠玩法的增多,一个商品所能享受的优惠越来越多,配置也越来越复杂,极易配置错误造成线上事故;
为此我们开始促销系统二期的能力建设,着重解决以上运营痛点:
- 提供时光穿越功能,实现用户能够“穿越”至未来某个时间点,从而实现促销活动的提前点检;
- 提供价格监控功能,结合「商城营销价格能力矩阵」规划的能力,通过事前/事中/事后多维度监控措施,来“降低出错概率,出错能及时止损”。
2.2 促销与优惠券
促销的主要目的就是向用户传递商品的各种优惠信息,提供优惠利益,吸引用户购买,从而起到促活拉新、提高销量的目的。从这种角度来看,优惠券也属于促销的一部分。
但因一些原因vivo商城促销系统独立过程中,并没有与促销系统放一块:
- 首先,优惠券系统在商城v2.0时就已独立,已经对接很多上游业务,已经是成熟的中台系统;
- 再者,就是优惠券也有相较与其它促销优惠的业务特殊性,如有发券、领券能力。
在考虑设计改造成本就未将优惠券包括在促销系统能力范畴,但优惠券毕竟也是商品价格优惠的一部分,因此促销计价需要依赖优惠券系统提供券优惠的能力。
2.3 业务架构&流程
至此我们也就梳理出整个促销系统的大概能力矩阵,整体架构设计如下:
(图2-3. 促销系统架构)
而随着促销系统独立,整个商城购物流程与促销系统的关系如下:
(图2-4. 最新商城购物流程)
三、技术挑战
作为中台能力系统,促销系统面临的技术挑战包括以下几方面:
- 面对复杂多变的促销玩法、优惠叠加规则,如何让系统具备可扩展性,满足日益多变的优惠需求,提升开发与运营效率。
- 面对新品发布、双11大为客户等大流量场景,如何满足高并发场景下的高性能要求。
- 面对来自上游业务方的不可信调用,以及下游依赖方的不可靠服务等复杂系统环境,如何提升系统整体的稳定性,保障系统的高可用。
我们结合自身业务特点,梳理出一些技术解决方案。
3.1 可扩展性
扩展性提升主要体现在两块:
- 优惠模型的定义,对所有优惠活动抽象出统一的优惠模型和配置管理界面;
- 促销计价引擎的建立,计价模型的统一。
相关的详细设计内容,会有后续文章进行说明。
3.2 高并发/高性能
缓存
缓存几乎就是解决性能问题的“银弹”,在促销系统中也大量使用缓存进行性能提升,包括使用redis缓存与本地缓存。而使用缓存就需要关注数据一致性问题,redis缓存还好解决,但本地缓存不就好处理了。因此本地缓存的使用要看业务场景,尽量是数据不经常变更且业务上能接受一定不一致的场景。
批量化
促销系统的业务场景属于典型的读多写少场景,而读的过程中对性能影响最大的就是IO操作,包括db、redis以及第三方远程调用。而对这些IO操作进行批量化改造,以空间换时间,减少IO交互次数也是性能优化的一大方案。
精简化/异步化
简化功能实现,将非核心任务进行异步化改造。如活动编辑后的缓存处理、资源预占后的消息同步、拼团状态流转的消息通知等等。
冷热分离
对于读多写少场景对性能影响最大的除了IO操作,还有就是数据量,在促销系统中也存在一些用户态数据,如优惠资源预占记录、用户拼团信息等。这些数据都具备时间属性,存在热尾效应,大部分情况下需要的都是最近的数据。针对这类场景对数据进行冷热分离是最佳选择。
3.3 系统稳定性
限流降级
基于公司的限流组件,对非核心的服务功能进行流量限制与服务降级,高并发场景下全力保障整体系统的核心服务
幂等性
所有接口均具备幂等性,避免业务方的网络超时重试造成的系统异常
熔断
使用Hystrix组件对外部系统的调用添加熔断保护,防止外部系统的故障造成整个促销系统的服务崩溃
监控和告警
通过配置日志平台的错误日志报警、调用链的服务分析告警,再加上公司各中间件和基础组件的监控告警功能,让我们能够第一时间发现系统异常
四、踩过的坑
4.1 Redis SCAN命令使用
在Redis缓存数据清除的处理过程中,存在部分缓存key是通过模糊匹配的方式进行查找并清除操作,底层依赖Redis SCAN命令。
SCAN命令是一个基于游标的迭代器,每次被调用之后都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
对于使用KEYS命令,SCAN命令并不是一次性返回所有匹配结果,减少命令操作对Redis系统的阻塞风险。但并不是说SCAN命令就可以随便用,其实在大数据量场景下SCAN存在与KEYS命令一样的风险问题,极易造成Redis负载升高,响应变慢,进而影响整个系统的稳定性。
(图4-1 Redis负载升高)
(图4-2 Redis响应出现尖刺)
而解决方案就是:
- 优化Redis key设计,减少不必要的缓存key;
- 移除SCAN命令使用,通过精确匹配查找进行清除操作。
4.2 热点key问题
在促销系统中普遍使用redis缓存进行性能提升,缓存数据很多都是SKU商品维度。在新品发布、特定类型手机大促等业务场景下极容易产生热点Key问题。
热点Key具有聚集效应,会导致Redis集群内节点负载出现不均衡,进而造成整个系统不稳定。该问题是普通的机器扩容无法解决的。如下图某次线上摸排压测时redis负载情况:
常用的解决方案有两种:
- 散列方案:对Redis Key进行散列,平均分散到RedisCluster Nodes中,解决热点Key的聚集效应。
- 多级缓存方案:对热点Key增加使用本地缓存,最大限度加速访问性能,降低Redis节点负载。
我们是采用多级缓存方案,参照优秀的开源热点缓存框架,定制化扩展出一整套热点解决方案,支持热点探测 、本地缓存 、集群广播以及热点预热功能,做到准实时热点探测并将热点Key通知实例集群进行本地缓存,极大限度避免大量重复调用冲击分布式缓存,提升系统运行效率。
五、总结
本篇属于vivo商城促销系统概览介绍篇,简单回顾了vivo商城促销系统业务能力建设历程及系统架构,并分享遇到的技术问题与解决方案。后续我们会对促销系统的核心功能模块(优惠活动管理、促销计价、价格监控和时光穿越)的设计实践进行逐个分享,敬请期待。
作者:vivo互联网官方商城开发团
相关推荐
- Java面试题及答案总结(2025版)
-
大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Redis、Linux、SpringBoot、Spring、MySQ...
- Java面试题及答案最全总结(2025春招版)
-
大家好,我是Java面试分享最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Spring...
- Java面试题及答案最全总结(2025版持续更新)
-
大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...
- 蚂蚁金服面试题(附答案)建议收藏:经典面试题解析
-
前言最近编程讨论群有位小伙伴去蚂蚁金服面试了,以下是面试的真题,跟大家一起来讨论怎么回答。点击上方“捡田螺的小男孩”,选择“设为星标”,干货不断满满1.用到分布式事务嘛?为什么用这种方案,有其他方案...
- 测试工程师面试必问的十道题目!全答上来的直接免试
-
最近参加运维工程师岗位的面试,笔者把自己遇到的和网友分享的一些常见的面试问答收集整理出来了,希望能对自己和对正在准备面试的同学提供一些参考。一、Mongodb熟悉吗,一般部署几台?部署过,没有深入研究...
- 10次面试9次被刷?吃透这500道大厂Java高频面试题后,怒斩offer
-
很多Java工程师的技术不错,但是一面试就头疼,10次面试9次都是被刷,过的那次还是去了家不知名的小公司。问题就在于:面试有技巧,而你不会把自己的能力表达给面试官。应届生:你该如何准备简历,面试项目和...
- java高频面试题整理
-
【高频常见问题】1、事务的特性原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。一致性或可串性:事务的执行使得数据库从一种正确状态转换成另一种正确状态隔离性:在事务正确提交之前,不允许把该...
- 2025 年最全 Java 面试题,京东后端面试面经合集,答案整理
-
最近京东搞了个TGT计划,针对顶尖青年技术天才,直接宣布不设薪资上限。TGT计划面向范围包括2023年10月1日到2026年9月30日毕业的海内外本硕博毕业生。时间范围还...
- idGenerator测评
-
工作中遇到需要生成随机数的需求,看了一个个人开发的基于雪花算法的工具,今天进行了一下测评(测试)。idGenerator项目地址见:https://github.com/yitter/IdGenera...
- 2024年开发者必备:MacBook Pro M1 Max深度体验与高效工作流
-
工作机器我使用的是一台16英寸的MacBookProM1Max。这台电脑的表现堪称惊人!它是我用过的最好的MacBook,短期内我不打算更换它。性能依然出色,即使在执行任务时也几乎听不到风扇的...
- StackOverflow 2022 年度调查报告
-
一个月前,StackOverflow开启了2022年度开发者调查,历时一个半月,在6月22日,StackOverflow正式发布了2022年度开发者调查报告。本次报告StackO...
- 这可能是最全面的SpringDataMongoDB开发笔记
-
MongoDB数据库,在最近使用越来越广泛,在这里和Java的开发者一起分享一下在Java中使用Mongodb的相关笔记。希望大家喜欢。关于MongoDB查询指令,请看我的上一篇文章。SpringD...
- Mac M2 本地部署ragflow
-
修改配置文件Dockerfile文件ARGNEED_MIRROR=1//开启国内镜像代理docker/.envREDIS_PORT=6380//本地redis端口冲突RAGFLOW_IMA...
- 别再傻傻分不清!localhost、127.0.0.1、本机IP,原来大有讲究!
-
调试接口死活连不上?部署服务队友访问不了?八成是localhost、127.0.0.1、本机IP用混了!这三个看似都指向“自己”的东西,差之毫厘谬以千里。搞不清它们,轻则调试抓狂,重则服务裸奔。loc...
- 我把 Mac mini 托管到机房了:一套打败云服务器的终极方案
-
我把我积灰的Macmini托管到机房了,有图有真相。没想到吧?一台在家吃灰的苹果电脑,帮我省了大钱!对,就是控制了自己的服务器,省了租用云服务器的钱,重要数据还全捏在自己手里,这感觉真爽。你可...
你 发表评论:
欢迎- 一周热门
-
-
Redis客户端 Jedis 与 Lettuce
-
高并发架构系列:Redis并发竞争key的解决方案详解
-
redis如何防止并发(redis如何防止高并发)
-
Java SE Development Kit 8u441下载地址【windows版本】
-
开源推荐:如何实现的一个高性能 Redis 服务器
-
redis安装与调优部署文档(WinServer)
-
Redis 入门 - 安装最全讲解(Windows、Linux、Docker)
-
一文带你了解 Redis 的发布与订阅的底层原理
-
Redis如何应对并发访问(redis控制并发量)
-
Oracle如何创建用户,表空间(oracle19c创建表空间用户)
-
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (83)
- php redis (97)
- redis 存储 (67)
- redis 锁 (74)
- 启动 redis (73)
- redis 时间 (60)
- redis 删除 (69)
- redis内存 (64)
- redis并发 (53)
- redis 主从 (71)
- redis同步 (53)
- redis结构 (53)
- redis 订阅 (54)
- redis 登录 (62)
- redis 面试 (58)
- redis问题 (54)
- 阿里 redis (67)
- redis的缓存 (57)
- lua redis (59)
- redis 连接池 (64)