标签平台作为数据平台建设的一部分,尤其是在互联网电商平台中,有着重要的作用。本人在公司接手并且重构了整个标签平台的核心逻辑。对标签平台有一定的了解。写这篇文章的契机是几个数仓的哥们,问到了这方面的问题,正好我也可以总结一下。
本文从技术角度,通过以下几个方面来阐述标签平台的建设历程
特征:对某个维度特征的描述,特征也是标签,只不过是原子维度的标签。
标签:一组特征的组合。
实验: 一组相似或者完全不同的标签的组合,主要做某种优化的尝试。
特征就是对某个维度的描述,比如人,有各种固定的属性(年轻,身高,体重),行为的维度(一天挣多少钱,喜欢什么颜色)这些也可以归结为特征。而标签更好理解,标签就是一组特征的组合。从广义上来讲标签和特征是一类东西。叫法不一样而已。
特征大致分为三类:
统计型特征
一些基础的属性比如年龄,城市星座,和一些通过统计数据中得到的(活跃时常,活跃天数等)。这些基础属性和统计类属性构成了特征的基础
规则型特征
通过一些规则产生。一般是对一些统计型标签估计量化形成业务可以看懂的特征。这类特征在业务上比较重要,因为一般使用平台的都是运营的同学,这些已知规则的标签,业务的同学才能看得懂。比如针对商品的一些标,双11大促标,7天无理由退货标等等。
机器学习挖掘型
通过机器学习挖掘产生,比如判断用户性别,用户购买偏好,流失意向,一般开发成本比较高,占比较小。
特征是标签平台的基础,一般而言,特征越丰富,圈选的标签就越丰富,所以有时候就会有一个误区,数仓同学在开发特征的时候,直接就是把业务的各种大宽表导入进来。从业务上看大而全,但是实际应用中很多特征一次都没有用过。在我们的一些经验里面,应该把基础特征做全,其他根据业务的需求增量去开发,避免一些无用特征的浪费,而且还要根据特征的使用情况,淘汰掉一些使用度很低的特征。
特征/标签的口径说明应该是特征/标签体系中最重要的部分,特征的口径/说明决定了特征的使用度。从系统开发的角度,一方面是尽量提供明确的口径说明,血缘关系,特征的联系人,从应用的角度。尽量多创建一些通用的规则型特征,方便业务方使用。
在狭义的理解中,标签平台就是做标签圈选的。以某电商标签平台为例,可以给用户打标签(年龄,职业,收入…),也可以给商品打标签(颜色,尺寸,类型…),当然也可以给商家打标签(星级, 排名)。
但是特征从哪里来?标签怎么组装?标签怎么存储?如何进行标签分析?数据如何回流?这些都是在标签平台的范畴之内。先整理了一个标签从特征生产,特征组装成标签, 查询引擎一整个流程。给大家一个直面的认识。如下图:
标签平台包含特征,标签,查询三个大块,这几大块组合起来就是一个标签平台。但是从狭义上来讲,特征平台又是单独的,查询引擎可以归属到数据平台统一数据服务中。所以标签平台其实是多个系统的整合。
我这边只从互联网电商平台的角度说一下应用的场景
在这几类中应用最多的是推送,投放场景。其实风控,商品其实是很好的切入点(风控的人群定位,自定义搜索相关性商品)。有很多的应用场景。我们的标签平台最初是基于用户来做的,毕竟数据量庞大,在投放,推送中有重要的地位。
在几种应用场景中,都要根据业务进行定制化的开发,比如说投放场景,我们开发了kv存储和标签平台进行绑定。这些其实都已经跨业务域了。但是从另外一个角度上来说,平台只有和业务结合,才能更好的服务于业务。
在1.0版本中我们遇到了因为业务量疯狂增长,sql脚本增长太快,而且复用度很低的情况。而且运营同学一般不会sql,开发周期拉长。
在2.0版本中运营同学可以方便的通过映射组装sql。但是底层映射其实包含了大量元数据的映射。数仓同学做了很多大宽表,但是很多字段都是闲置状态,大部分都浪费了。
在3.0版本中,我们引入了特征平台,把离线特征下沉到es,实时特征下沉到kv。这样把特征从标签平台一整套中剥离出单独的应用。方便了系统的管理。在2.0版本中做特征,标签分析,需要依赖spark。不能做到秒级别返回。用户体验很差。但是在3.0版本中es对于亿级别数据各种聚合类查询,能达到毫秒级返回。完全能够满足我们日常的使用需求。
实时特征在flinksql的普及之下, 业务的同学不同纠结于做各种正则解析,口径对比了。只负责拿到kafka对应的字段,然后批量插入到kv就行,其他交给数仓的同学。并且我们针对实时的分析场景引入了tidb(后面tidb下线,后续迁移到clickhouse)。
标签平台是一个融合的系统,包含了离线特征平台,实时特征平台,标签调度平台,标签组装与分析平台,查询引擎几部分组成,具体如图
一般来说,es数据一般是全量,这个全量可以使用全量join增量数据得到。
这种场景下es有自己的缺陷,无法使用历史的数据。所以有历史需求的,可以考虑自定义sql。
实时特征主要依赖flink实时数仓来实现,实时数仓负责进行ETL和口径的梳理,平台只负责批量导入到kv即可。
在最终存储这块,我们做了多数据源存储的方式,在最初的模型里面,我们使用kv,tidb,hbase三种存储。做了存储,分析,高可用。
实时特征导入到kv会有历史数据的追溯的问题,这个在以往的经验,找个相同口径离线sql然后导入到kv。这个是要和实时特征一块维护起来的。万一kv挂了之后可以通过任务来找回历史(当然你可以存储到hbase里面,不过高并发的场景不一定适合。)。
标签的组装,主要是标签的关系,特征的拼装。特征的类型和前端展示。下面列出的是字段类型和页面的显示类型。
字段类型 | 前端展示类型 |
---|---|
boolean | 等于/不等于 |
字符串枚举 | 包含/不包含 |
字符串 | 手工输入 |
数字枚举 | 包含/不包含 |
数字 | 手工输入 |
数字偏好类 | 多输入框 |
日期 | 普通日期/动态日期 |
特征的关系,这个可以参考下神策的做法,我个人觉得神策的平台页面做的不错。我们的系统其实和神策的类似,不过可操作性确实没有神策好。扯远了。标签的关系,其实就是且或非。且或可以自己实现一套解析和反解析的逻辑。非的逻辑其实挺有意思的。有些需要在特征的时候就要做非。有些可以通过运算符来做。比如实时的特征(ag: 是否是平台的vip会员,一般在kv里面只存储一种特征值,我们在筛选非平台会员的时候就是这种场景)(下图参考了神策)
标签的调度 这个主要是涉及到标签状态机的转换。具体的状态根据业务的不同也有所不同。
标签平台的调度在最初的时候是自己开发了一个小小的应用级调度。其实可以融入到数据平台的DAG调度中,标签平台只负责标签元数据管理和状态机的转变。
标签分析是标签平台的核心功能。标签分析包括特征的分析,标签特征分析,标签差异度。标签模型实验分析。
在标签分析中一般分为事前,事中,事后三个阶段:
在整个分析的场景中,数据回流和分析模型的沉淀是两个比较重要的点。一般而言,1:分析的场景一般在离线场景比较多。一般以spark作为分析的引擎,有时候需要添加一些算法进去。所以数据一般需要从es或者其他数据源导入到hive中进行分析。2:分析的模型一般都比较固定,但是需要结合前端页面的展示才能方便用户进行分析,各种图的对比展示才能一目了然标签的差异。
标签分析需要跨部门合作。标签的效果数据通过业务部门得到。然后再通过标签分析的模型进行效果分析。这是一个偏应用的场景。标签分析模型和分析数据回流的模型,是标签分析最重要的。
查询引擎在数据平台中,其实应该算是统一数据服务层的逻辑,不过因为查询引擎涉及具体的逻辑计算,所以单独拎出来。在我们的场景下,一般只用kv做存储。所以并发量是很可观的。而现在kv又做了主备。其实并不用太关心kv挂掉的情况,如果你实在担心,只能再多存储一份到hbase了。其实也是可以的。
表达式匹配的话,我用的是googlecode aviator来做的。相对旧版本匹配效率提升了不少。不过这里面有个坑,在这就不展开说了。
在整个离线/实时数据存储上,hdfs,kv是两个相对重要的存储。kv存储引擎的数据结构如下:
离线特征一般存储在hive,经过hbase中转导入到es作为查询服务,实时特征一般经过kafka存储到kv。在整个标签组装存储过程中,数据流转到hdfs和kv,并且把标签的数据回流到hive。并且最终通过查询服务暴露给第三方业务系统。第三方业务系统把使用后的数据和效果反馈给离线数仓和标签的数据结合起来进行进一步的数据效果分析。
这是一整套数据的链路。最重要的一点就是数据的回流。数据只有流转起来标签平台的价值才会体现出来。
在整个平台的建设中,我们发现数据的流转和回流是最困难的。数据来源很多(外部数据,业务系统数据,其他等),整合到一起,并且沉淀到分析模型中,形成数据流转。所以我们在整合整个系统架构,以及在存储的选择上,都是根据这些已有的业务场景选择一个折中的方案。这个需要和业务有着很深的联系。
整个标签平台的逻辑大致就是这样。我们的系统是在业务规模不断扩大,以及场景的不断丰富而迭代出来,不是一蹴而就,我是以一个开发的角度去看整个架构的,其实会缺少很多东西。但是似乎好像缺少了点什么东西。对的,偏分析的场景,这个到底算不算标签平台的一部分,其实是值得思考的。如果是两个分开的平台,其实会有一些割裂。比如外投的一些效果,怎么回流到标签平台做分析,推送的数据,用户的效果分析,以及如何进一步的优化标签的圈选效果。这些是值得思考的。
在整个标签平台的建设中其实更应该站在用户的角度上去思考问题,我们遇到了一些问题,这个可以给大家分享一下:
神策数据
神策标签生产引擎架构
用户画像总结