作者| 阿里文娱高级开发工程师  臻龙

责编 | 屠敏

头图 | CSDN 下载自视觉中国

背景介绍

随着在线视频行业数十年的发展,各家的会员业务,尤其是会员规模都已进入成熟期,呈现饱和状态。会员营销,不论是针对现有市场的精细化营销,还是针对下沉市场的定向营销,都需要更加针对性的打法。在这复杂需求背后,是强大营销系统的支撑。下面,我将分享优酷营销系统的技术实践经验。

面临的挑战

1.场景复杂多变

会员营销的场景复杂多变,具体归纳总结是四类:折扣,买赠,领取,发放,支撑起优酷站内,(阿里生态)二三方,优酷OTT等多个业务方的营销需求。

营销场景一:折扣类。在商品维度,可以是简单的普通活动的折扣,也可以是可选优惠券与普通普通折扣,支付渠道与普通活动折扣的叠加折扣。订单维度,可以是单个订单的折扣优惠,也可以是多个子订单的组合折扣优惠;

营销场景二:买赠类。赠送的权益,有虚拟的会员权益,也有阿里生态二三方合作方的联合会员权益,比如88VIP,当然也可以是实物类的商品;

营销场景三:领取类。不同的业务需求方,会根据自身业务诉求和业务目标,配置不同营销领取能力的营销策略。因业务而异,因目标而变换;

营销场景四:发放类。符合业务逻辑,主动给用户发放一定权益。业务逻辑也呈现多样化,比如预约影片,可以给用户发放观影体验特权;观影过程中,满足观影时长,发放用户成长值等等。

从以上四类场景出发,每年每季度都会出现新的玩法创新。比如,折扣的叠加,折扣买赠类的叠加、多个折扣能力互斥、折扣并领取的组合式营销等等。反馈到后端的营销系统上,不能一味的定制化开发,而是需要提供给运营同学,灵活的编排优惠的能力,并且实现复杂业务需求组合,快速拿到实验结果数据,帮助运营及时调整策略,最终实现业务价值的最大化。

2.系统要求高可用,低延时

除了单独的系统能力,营销系统还担负着与交易系统核心节点的优惠实现的使命,高可用,低延时的系统接口必不可少。如果优惠透出与下单场景的系统接口性能差,优惠透出问题凸显,会影响用户的下单意愿和交易的订单与支付;如果接口耗时大,会带来交易渲染与下单的价格不一致,用户无法得到看到的优惠,引发严重的客诉行为,更甚会造成很大的法务风险。

业务的特殊性,要求营销系统业务核心接口,必须高可用,高性能,低延时,稳定性才能保证用户良好的营销体验。

 

优酷会员营销系统的架构实现

1.活动规则化,QL语言实现

活动规则化,即将业务条件抽象成业务规则,依据业务逻辑对流程进行编排。

营销活动的业务规则抽象,即符合一个流程中所有节点中的规则条件,才能符合该活动。基于对业务的划分,最常见的规则有人群规则,会员身份规则,次数规则,商品规则,库存规则等等。

同一个活动模型下,通过对活动最小单元的规则选取和流程的编排,可以扩展出适用于不同业务场景的优惠活动,真正实现灵活快速的支撑业务。

如何实现业务规则抽象能力?如何将规则的实现侵入性降到最低?优酷会员营销系统采用阿里集团推荐的QL语言,一个轻量级的类java语法规则引擎,嵌入式规则引擎更加灵活。

该技术选型支持标准的JAVA语法,自定义操作符号重载,支持函数定义、宏定义,弱脚本语言,使用灵活,整个运算过程通过 ThreadLocal 来保证线程安全,资源消耗少,不会new新的对象,是使用缓存池技术实现。

QLExpress脚本引擎详解

2.    统一营销架构升级,核心引擎实现

上节的营销系统,能满足90%以上的营销需求。接下来的难点是单一优惠形式向复杂的组合优惠形式的转变。单一优惠形式问题凸显,无法支持优惠叠加,优惠价格体系薄弱,核心引擎比较弱,复杂场景难以支撑,维护成本太高。

基于以上的问题点,我们作出了架构升级以及核心营销节点的优化。以新的优惠券能力扩展为契机,抽象出统一营销的能力,实现各种优惠能力的统一。在统一营销的管理下,实现各种优惠能力的互斥与叠加,通过核心引擎的价格等优惠计算,最终输出给交易系统。

有了这样一个统一营销架构之后,不仅仅是针对优惠券的叠加优惠能力,更加可以灵活的扩展增加其他优惠能力,最终数据合理的数据结构,能够描述多种优惠能力的组合,给用户带来更加丰富的营销体验。

统一营销架构示意图

一个复杂的,具备多种优惠能力的统一营销系统,其核心引擎是怎样实现的呢?引擎核心实现如下:

  • 优惠请求上下文,优惠请求信息获取

  • 优惠模型定义,不同优惠类型的模型定义

  • 优惠分类引擎,根据优惠类型进行数据分类,业务规则生成优惠组合序列

  • 优惠计算上下文,将优惠组合序列的计算上下文透传給计算引擎

  • 优惠计算引擎,对优惠组合序列,进行顺序的价格计算,并支持多币种

  • 优惠计算结果,针对不同的优惠组合序列,输出不同的计算结果,生成以组合、文案、优惠、价格等信息组合的优惠数据结构

  • 计算结果排序,多重维度排序后,输出优惠信息

核心引擎实现示意图

3.  服务如何做到低延时,高可用

3.1 多缓存存储实现

采用LocalCache本地缓存与KV存储的分布式缓存相结合的方式。

首先将活动基础数据,规则数据,收获数据等数据量小,且访问非常频繁的活动数据,缓存到本地缓存中。分布式集群中每个JVM都有缓存,需要有实时的广播消息监听,感知活动数据的更新,实现增量的更新机制。同时我们也完善了全量数据的更新机制,保证全量数据的一致性。

其次将用户参与活动次数等用户维度数据,进行分布式缓存的存储并落盘。作为DB的数据缓存,提供给分布式集群查询校验次数的快速高性能的查询服务,减少对DB的查询依赖。DB的实时变更的binlog消息提供给KV存储做准实时数据同步。

营销缓存体系架构示意图

3.2 多线程匹配实现

以交易营销核心节点为细分,将渲染,下单,发放收获等核心节点分类,各自业务节点都采用多线程实现,依据业务类型不同,设置各自的线程池大小,并合理规定线程任务队列,多余线程的超时自动销毁,保证系统最优化。

多线程实现使用ExecutorService、Callable、Future实现有返回结果。执行Callable任务,获取到一个Future的对象。在该Future对象上调用get就可以获取到Ca任务返回的Object。值得注意的是get方法是阻塞的,直到等待全部线程返回结果。

线程池该设置多少个线程合适,如何设置才能使得系统性能最优,在这里不做详细展开,可以搜索相关资料学习。其中线程池核心参数如下:

  • corePoolSize:线程池核心线程数量

  • maximumPoolSize:线程池最大线程数

  • keepAliveTime:线程数大于核心线程数时,多余的空闲线程存活的最长时间

  • unit:单位时间

  • workQueue:任务队列,用来储存等待执行任务的队列

  • threadFactory:线程工厂,用来创建线程,一般默认即可

活动多线程匹配示意图

3.3 异步化收获实现

优惠活动收获的发放是与交易系统的支付成功调用紧密联系在一起。支付的成功在交易发放会员权益的同时告知营销发放阿里生态二三方赠送权益。由于二三方权益接口性能不一,为了实现高性能接口服务能力,采用异步化发放权益+重试失败的机制实现。

交易支付成功后,通知营销发放权益,发放通知进入业务消息,营销平台订阅消息,将权益发放出去,针对失败的处理告知消息later,为下一次重试做准备,并设定重试次数限制。以幂等ID为标识,保证权益发放唯一性。

收获异步重试示意图

3.4 分布式事务实现

复杂的业务逻辑,高并发的业务场景,尤其是交易营销类业务节点,要保证业务的一致性,缺少不了锁的实现。

交易营销的下单流程,针对限制次数的高价值优惠能力,要保证业务处理的运行中用户数据的一致性,需要对业务节点加锁。活动的下单节点采用的是分布式锁,通过业务规则确定锁的唯一标识,同时是可重入锁。锁的实现注意了业务加锁与业务解锁,并设置了锁的超时时间,保证锁高可用。

为了保证业务流程的一致性,还有库存锁的实现。了解MySQL的读者都清楚,MySQL是插件式存储引擎结构,分为两层:一层是MySQL Server层;另一层是存储引擎层。我们采用QUEUE_ON_PK在Server层排队,减少kernel_mutex在并发场景下对资源的竞争;依赖DB的行级锁,避免使用乐观锁在高并发场景下导致业务的失败,提升了业务处理成功率。

总结建议

以上是营销平台如何高效支撑营销需求的实践方案,总结下来有主要两点:

一是系统架构设计要通用,灵活,扩展,才能高效支撑业务多变;

系统架构设计要充分考虑通用性和扩展性,尤其是支撑复杂多变的业务系统。在设计系统的同时考虑到未来业务的方向,反复推敲系统架构的合理性。至于灵活性,对系统模块进行详细的拆解与划分,灵活运用适合业务的设计模式,做到可复用。

二是复杂的业务逻辑背景下,高可用低延时的服务设计要多维度合理化实现;

简单的业务实现考虑合适的设计模式,复杂的业务实现考虑整体的性能优化实现。缓存,多线程,协程,异步,重试,锁实现,分布式最终一致性等等要结合业务处理本身,而不是硬怼上去,更多的是考虑其实现的合理性。

更多精彩推荐
☞急缺芯片,高通是华为的唯一选择吗?
☞征战云时代,为什么安全是关键命题?
☞人均月薪 7.5 万,腾讯 Q2 成绩单来了,网友酸了?
☞为什么气象站和 AI 都测不准天气?
☞2019年中国IaaS公有云市场排名及份额出炉
☞马小峰:金融科技界的区块链博士
点分享点点赞点在看
Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐