• vivo积分任务体系的架构演进-平台产品系列05


    作者:vivo 互联网平台产品研发团队- Mu JunFeng

    积分体系作为一种常见营销工具,几乎是每一家企业会员营销的必备功能之一,在生活中随处可见,随着vivo互联网业务发展,vivo积分体系的能力也随之得到飞速提升,本篇主要介绍vivo积分任务体系的系统建设历程。

    一、前言

    1.1 什么是积分体系?

    积分体系如今越来越普遍,是很多线上线下商家都会采用的用户消费激励体系,例如:淘宝的金币、京东的京豆等;此外,各大运营商、航空公司、连锁酒店、线下商超等也都有自己的积分玩法。积分的价值是连接用户,增加活跃、保持用户粘性。通过增加用户积分价值感的手段,实现业务内循环。

    vivo积分体系能力已经非常丰富,主要包括以下能力:

    • 积分商城:积分体系主入口,提供丰富的礼品兑换、活动玩法,强化积分价值感知

    • 任务中心:重要的积分获取入口,引导用户了解业务、培养用户习惯的重要玩法

    • 活动中心:提供丰富的活动玩法,增加积分体系的可玩性和丰富度,更好地提升用户参与度

    vivo积分贯穿整个vivo生态下的互联网应用,同时手机厂商互联网业务的独特性(不仅局限于单一类型业务)也造就了vivo积分与其他行业生态积分体系的差异性,这些差异性着重体现在vivo积分是与各个业务形态紧密合作,相互渗透。如下图例显示在对应签到、任务中心都与业务方强相关联。

    图片

    在积分体系里任务体系是很重要的一环,行业内会基于任务的形式刺激用户活跃,引导用户完成业务上高价值的行为,最终给予用户回馈(发放积分)。

    1.2 什么是任务?

    玩过游戏的同学都知道,游戏内日常都会有任务,有目的地指引玩家进行游戏活动,并给予玩家一定奖励。

    对于积分产品(业务)而言,任务体系一般希望引导用户了解产品、提高产品活跃度、培养用户习惯,总而言之是期望用户在使用产品的过程中不断产生价值行为,通过直接或间接的方式帮助业务方达成业务指标,同时用户因完成任务得到奖励,有持续产生高价值行为的动力,最终形成正向循环。

    1.3 福格模型

    基于以上分析我们可以看出积分任务体现出来的是典型的“福格模型”,通过合理的奖励去推动符合业务价值的行为。

    图片

    (图片来自网络,混沌大学)

    福格行为模型是一个用来探寻用户行为原因的模型,它认为要让一个行为发生,必须同时具备三个元素:动机、能力、触发器

    也就是说,只有当一个人有足够的动机,并且有能力去做到,而且有能触发用户行动的触发器来提醒的时候,一个行为才最终可能发生。

    那么vivo的任务体系是如何搭建的呢,系统建设又走过了哪些历程?在本次文章中我们将为大家慢慢揭晓。

    二、发展

    2.1 阶段一:初探

    (1)业务模型分析

    • 任务模型:“用户 A 完成了 B 动作发放 C 奖励(或者触发某种逻辑)”,我们将满足这种模式的需求定义为一个任务。

    • 任务周期:结合业务场景,我们发现任务周期大致分为:新手任务(全局只能完成一次)、每日任务、每月任务。

    • 任务状态:存储业务状态,包括任务的完成状态,以及奖励领取状态。

    (2)系统目标

    • 快速配置任务,按周期以及业务场景确定任务类型

    • 记录任务完成状态及奖励领取状态

    (3)实现方案

    图片

    :上图中“业务方”特指vivo生态下的服务方;“端侧”特指客户端APP。

    如上图所示,阶段一的设计方案虽然有配置,但在逻辑层还是有很大的开发成本, 在阶段二我们着重解决定制化开发效率的问题。

    2.2 阶段二:用户行为激励体系建设

    (1)痛点分析

    积分任务中心初版在线上运行一段时间后发现,虽然任务基础信息可以通过配置化完成,但远没有达到预期:通过配置化就能够实现任务快速上线

    回顾阶段一的设计,其实仅仅是引入了任务的定义与配置,但任务的行为以及达成判定都由业务方实现,在项目对接上有不少弊端

    • 跨项目协作周期长:跨项目管理难度大,进度对齐、沟通协调,case by case开发,系统耦合严重,灵活性低,业务方逻辑重、开发成本高。

    • 业务上运营效率低:一个季度上线不了几个任务,加上数据分析周期,整体跨度长,效果不理想。

    通过分析积分任务的业务场景,我们发现大多数任务行为都是app端侧产生的行为,比如用户在浏览器端浏览新闻给予积分奖励。

    结合互联网业务都有日常埋点,我们很容易想到可结合埋点上报捕获用户行为,同时为了解决我们初版任务系统的弊端,我们重新梳理出vivo积分任务系统需要支持的核心功能点

    • 引入行为模型:建设集行为定义、采集、计算、触达为一体的模型体系

    • 建设行为SDK:拉取行为配置、上报行为、行为在端侧支持过滤、任务完成触达提醒

    • 支持实验能力:支持任务灰度测试能力,同时支持基于用户标签定向投放任务

    (2)行为上报流程

    (3)方案交互序列图

    整体流程:

    • App 端启动时激活行为SDK拉取端侧行为配置

    • 行为SDK针对上报的行为埋点,经过匹配、过滤、去重等策略,最终将行为上报

    • 行为上报至服务端进行用户标签判断、实验策略判断、行为计算,最终将任务结果返回给行为SDK

    • 行为SDK接收到响应后将奖励结果通过toast/snackbar将配置的UI交互展示给用户,用户可手动领取积分奖励,或者自动发放

    (4)场景示例

    用户浏览新闻,点赞资讯评论,行为SDK上报此事件,判定达成任务,返回snackbar提示用户手动领取奖励。

    图片

    (5)业务效果

    经过以上升级,我们的任务系统可以支持以下能力:

    • 涉及埋点型任务,业务方可以优雅对接,不需要额外关心任务达成的判断,直接基于SDK透传埋点即可;

    • 新任务可以快速支持配置,业务方一次接入,后续零成本开发;

    • 基于用户标签、AB实验平台,支持任务实验配置能力,可快速验证任务上线效果。

    上线周期大大缩短:原行为类任务从需求评审,到设计开发测试上线,再到生产环境灰度测试,完整的周期可由原来的1-3个月缩短至1-3人天。

    2.3 阶段三:扩大行为采集源,丰富触达形式

    (1)痛点分析

    场景引入:

    某天游戏侧反馈希望接入我们的任务,但场景是“给游戏付费用户发送积分奖励,同时要求付费指定类型的游戏,且奖励的积分值根据付费金额而定(不同的区间给予不同的奖励,不足1元按1元计算)”。

    在剖析这个应用场景时,我们延展发现以下主要痛点

    • 行为采集源单一:非埋点行为类的任务不支持

    • 触达形式单调:只支持简单的toast以及snackbar

    为了解决以上痛点,我们做了多方面的技术调研。

    (2)业务模型

    图片

    从本质上业务模型并没有大的变化,依然是“收集行为、判定任务关联行为是否达成、任务的奖励发放、对用户的触达”,其实我们需要着重关注的是以下几点:

    • 行为采集源的拓展

    • 支持复杂行为计算

    • 动态的规则配置

    (3)数据采集层

    在数据采集层上我们尽可能覆盖更多的数据源,包括埋点、数据库(MySQL)、消息队列、API/RPC接口等,以下为当前数据采集的数据流向图:

    采集能力完善

    • 集群管理:不同的业务方、不同的任务,相应产生的数据量级各不一样,为了防止单点导致业务数据处理不及时,我们在设计上可以支持为采集任务动态配置集群,提升消息处理及时性。

    • 数据“源”管理:定义采集来源,可动态配置RocketMQ/Kafka消息,并支持动态创建监听器。

    • 元数据管理:定义指定采集行为的基础信息,包括行为事件存储介质、事件类型、过期时间、集合名等等。

    • 数据预处理:主要指数据过滤,通过对比排查,我们最终选择aviator的表达式引擎进行过滤处理。

    • 数据归一:业务方采集的源数据定义格式各一,为了数据计算层的统一,我们会将元数据进行“格式化”,便于后续统一处理。

    • 数据存储:源事件存储,在存储介质选择上我们有多维度的考量,数据量大、能够满足聚合计算、方便清理,最初我们选择了ES,但通过性能测试对比,ES在聚合计算时性能有明显的差距,最终我们选择了MongoDB以及TiDB。

    数据归一配置示例:

    图片

    (4)规则计算层

    图片

    事件的采集与计算层,我们在设计上将其独立开,采集层通过分布式消息将事件上报到计算层,经过计算最终将结果行为异步通知到任务层。

    规则配置示例:

    图片

    (5)表达式引擎

    再回到最初的业务场景需要“要求付费指定类型的游戏,且奖励的积分值根据付费金额而定(不同的区间给予不同的奖励,不足1元按1元计算)”,为了满足业务层灵活多变的逻辑需要,我们引入了表达式引擎,便于业务灵活动态调整。

    图片

    从多个维度的技术调研,最终我们选择AviatorScript做为我们的表达式引擎。

    AviatorScript是一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢?

    1. Aviator的设计目标是轻量级和高性能 ,相比于Groovy、JRuby的笨重,Aviator非常小,加上依赖包也才450K,不算依赖包的话只有70K;当然,Aviator的语法是受限的,它不是一门完整的语言,而只是语言的一小部分集合。

    2. Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都是通过解释的方式运行,而Aviator则是直接将表达式编译成Java字节码,交给JVM去执行。

    简单来说,Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎之间。

    表达式引擎使用示例

    // 数据清洗过滤
    originEvent.pay_status == 1 && string.contains("11,12,13,14,15,16,92,93,95", originEvent.product_type + "")
     
    // 规则计算
    let value = eventObject.value / 100;
    let success = value >= 1;
    return seq.map('success',success,'data',value);

    (6)任务层

    图片

    在应用层,用户直观感觉的任务层,主要包括以下逻辑:任务与行为的关联配置、任务的投放、任务的奖励发放、用户的触达、用户任务的状态。

    (7)触达层

    • 自定义弹窗:业务方可基于vivo建站平台自动创建丰富多彩的页面交互效果,异步事件任务可以基于push中转透传结果。

    • 消息透传:任务结果可通过MQ消息异步传递至业务方端侧,可消费转入消息盒子,或用作其他逻辑。

    触达交互示意图:

    图片

    三、整体系统架构

    图片

    四、服务稳定性

    4.1 系统防护

    • 服务降级:接入限流、熔断组件

    • 集群隔离:按业务场景做服务单元隔离,避免高并业务场景影响整个服务

    • 异步执行:非核心功能异步化(例如行为轨迹)、服务依赖方接口异步(例如请求业务方发放礼品)

    4.2 服务拆分

    大系统根据业务模块拆分,整个积分任务系统按业务职责主要拆分为如下几个系统:

    • 事件采集服务(事件采集、过滤、映射、存储)

    • 事件计算服务(事件计算、通知)

    • 任务服务(任务判定达成、奖励触达)

    4.3 服务监控

    • 系统监控:完善的CPU、日志中心告警、DB主从延时、消息积压、慢服务等

    • 数据监控:完成的行为事件链路监控,便于排查定位

    五、写在最后

    5.1 任务中心建设过程感想

    • 系统设计上需要关注业务模型抽象的能力,避免一开始就留坑;

    • 系统防护设计,常规套路:限流、熔断、降级、基于CAP理论执行;

    • 使用发展的眼光看待系统建设,系统的设计需要经过反复的迭代,不断完善,“稍稍跑在业务前面的技术架构”可能是最理想的。

    5.2 未来构思

    • 打造平台扩展能力:将任务能力封装完善,能够拓展对上层业务提供复用能力。

    • 奖励平台能力建设:当前任务发放的奖励主要形式为vivo积分,后续可进一步扩展,接入全品类的奖励类型。

    • 组合时序行为事件:当前业务上只支持单行为事件的采集,还不支持行为有前后依赖关系,或者多个行为事件共同达成后完成任务。

    • 实时计算能力提升:当前设计可能存在实时性波动的风险,例如MQ消息消耗阻塞、数据库binlog监听延迟,对实时性要求高的场景不友好。

    附:

    关于用户行为数据采集的私密性:很多人普遍认为SDK采集数据会涉及个人隐私,这主要还是不了解SDK数据采集的技术原理。

     

    SDK:Software Development Kit,直译过来就是软件开发包,用N行软件代码采集数据。SDK采集的任何数据都来自用户的主观行为,企业在正常商业活动中获取的个人隐私数据并不违反法规,而我们积分的任务其实是用户有意主动去完成行为而获得一定的收益,同时我们也通过隐私声明明确告知用户且获得用户同意。

  • 相关阅读:
    学习笔记12--路径-速度分解法之局部路径搜索
    RISC-V声名鹊起,究竟为何?
    【面试题】为什么Object.prototype.toString.call() 可以准确判断对象类型?
    MySQL:索引特性
    JNDI 、C3P0 、DBCP、JDBC、ODBC的区别
    PTL智能拣货系统
    【黄色手套22】7话:预处理和文件操作
    SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
    Vue.js之动态绑定组件
    这三个 Go 水平自测题,你手写不出来还是先老实上班吧,过来看看
  • 原文地址:https://www.cnblogs.com/vivotech/p/17370566.html