淘宝用户增长团队所在的用户运营平台技术团队是一支懂用户,技术驱动的年轻队伍,团队立足体系化打造业界领先的用户增长基础设施,以媒体外投平台、ABTest平台、用户运营平台为代表的基础设施赋能用户增长,日均处理数据量千亿规模、调用QPS千万级。
Bitmap是一种通过位(bit)来存储和操作数据的数据结构,具备高度的空间效率和计算效率。它在人群画像分析中,例如跟踪大型网站用户行为时,能够极大地节省存储空间,并提高处理速度。
原理描述:
如下图:有一堆用户id,其中用户id为3、4的用户是勇士球迷;如果用Bitmap表示的话,那么key是勇士球迷;value是Bit数组。那么最后用户id用Bitmap存储如下:
Bitmap的详细原理如下图:
从以上原理图可以看出,Bitmap可以将数据转化为数组位存储,不仅可以节约存储空间,也可以进一步提高查询效率。
虽然Bitmap已经让数据的存储空间有了N倍的缩减,但Bitmap的问题在于,不管业务中实际有多少个元素,它必须包含元素的最大值个bit空间,如果元素的取值范围是0-10亿,那么就要有10个bit空间,如果元素的取值比较稀疏,例如10亿个值中只有极少数据满足需求,那么这样的稀糊数据会造成严重的空间浪费,且也会占用大量的内存计算,所以我们一般还需要对Bitmap进行压缩处理。
RoaringBitmap根据实际的数据情况,动态地选择最适合的容器类型,从而实现了既高效的数据存储,又快速的数据查询。在做位图计算(AND、OR、XOR)时,RoaringBitmap提供了相应的算法来高效地实现在多个容器之间的运算,使得RoaringBitmap无论在存储和计算性能上都表现优秀。详细的实现原理图如下:
在实际的使用中一般使用RoaringBitmap来,并且官方也提供了对应的Java库地址,可以直接拿来使用。
技术用户画像分析是对一个或多个指定用户群,通过可视化的方式,可以多维、立体的展示用户群的画像信息,让运营更好的理解人群,实现人群细分及对个性化运营策略的制定提供能力支撑;在进行数据分析时,更加便捷的获得人群的特征信息,从而更好的进行定量的分析。
业务画像分析流程:
1、默认情况下平台有业务的所有标签在MaxCompute中存储,同时也会存储一份Bitmap的标签索引数据,再标签数据更新时构建。
3、圈选完人群后,就会进行画像分析,如果标签和人群都有Bitmap索引数据,就会通过Bitmap进行分析
技术平台早期画像分析主要依赖于MaxCompute执行SQL,但这种方式耗时较长,对于需要实时洞察分析的业务场景,分析需要更加快速看到结果,高延迟无法满足业务需求。之前尝试通过将数据导入Hologres进行加速,然而由于数据量庞大,Hologres的执行耗时仍然超过3分钟。
在前期,根据业务需求我们也在技术上做了一些调研。从技术方案角度看,一些可以实现的画像分析的方案和其缺点:
而Hologres原生支持RoaringBitmap数据结构,特别适合大数据量级下的交并差运算,并且在画像分析的场景天然适合,因此我们最后选择了RoaringBitmap方案。虽然RoaringBitmap会带来额外的处理和优化步骤、索引构建过程,这可能会带来一定的初期成本上升。然而,在我们的场景中,数据更新不是那么频繁,数据量级也在可控范围内,因此这一成本上升在可接受范围。而且使用RoaringBitmap带来的效率提升非常明显,最终还是选择使用这一方案进行标签和人群加速。
应用功能分层描述
标签RoaringBitmap构建结果表预估:假设每个标签平均有10个标签值,每个表存储1000个标签,按照2^20分桶,可以根据自己的业务进行计算。记录数=(用户量/2^20)*(标签个数*标签值)。因为记录通过分桶被极大的进行压缩,因此在Hologres的高性能查询支撑范围之内。
对于人群也是同理,数据量级会压缩2^20倍,因此Hologres的查询效率也会提升。业务可以按照自己的量级进行分桶设计:业务应根据具体场景进行测试,确定每个桶的最佳用户数。一般桶的用户数越多,越耗费CU,速度可能有一定提升。
分表策略:
目前按照:用户属性rb表、人群rb表都分16个表;都是对16进行取余,然后落到对应的表上。
Hologres内表:
Hologres外部表:
人群和标签表,新增字段:
publicclassAccelerateConfigDTO{privateBooleanisAccelerationCompleted;privateBooleanisAccelerationEnabled;privateStringlastDs;}3.5关键的业务SQL1)在用Java提交MaxCompute任务的时候,记得设置如下参数:
2)尽量选择以下几种类型的数据构建Bitmap
尽量选择性别、年龄、城市这种类型的有限的字段值构建bitmap,里面的value类型比较简单。MaxCompute中分桶以及构建bitmap的SQL如下:
说明:Bitmap通过在MaxCompute中构建UDF实现,不再本文中做详细描述
--MaxComputeSQL--创建表CREATETABLEIFNOTEXISTS空间名.demo表名(field_valueSTRINGCOMMENT'标签value值',bucketBIGINTCOMMENT'分桶',bitmapBINARYCOMMENT'uidbitmap')COMMENT'用户基础属性标签bitmap'PARTITIONEDBY(dsSTRINGCOMMENT'日期',label_idSTRINGCOMMENT'标签ID')LIFECYCLE365;--插入数据INSERTOVERWRITETABLE空间名.demo表名PARTITION(ds='${bizdate}',label_id='${label_id}')SELECTCOALESCE(${label_field},'NULL')asfield_value,SHIFTRIGHT(CAST(COALESCE(${uidField},'0')ASBIGINT),20)asbucket,ENCODE(mc_rb_build_agg(CAST(COALESCE(${uidField},'0')asBIGINT)&1048575),'utf-8')asbitmapFROM${dataSource}.${dataTable}WHEREds=MAX_PT('${dataSource}.${dataTable}')ANDCAST(COALESCE(${uidField},'0')ASBIGINT)>0GROUPBYCOALESCE(${label_field},'NULL'),SHIFTRIGHT(CAST(COALESCE(${uidField},'0')ASBIGINT),20);因为人群只包含uid的明细,构建起来会比较简单,并且快速。如下是在MaxCompute中分桶以及构建Bitamp,Bitmap通过udf构建。
--MaxComputeSQlCREATETABLEIFNOTEXISTS空间名.demo人群表名(bucketBIGINTCOMMENT'分桶',bitmapBINARYCOMMENT'uidbitmap',dsSTRING)COMMENT'奥格圈人bitmap表'PARTITIONEDBY(crowd_idSTRING)LIFECYCLE365;INSERTOVERWRITETABLE空间名.demo人群表名PARTITION(crowd_id='${crowd_id}')SELECTSHIFTRIGHT(uid,20)bucket,ENCODE(mc_rb_build_agg(cast(uidasBIGINT)&1048575),'utf-8')asbitmap,dsFROMcrowdSourceDemo--原始人群表WHEREcrowd_id='${crowd_id}'GROUPBYSHIFTRIGHT(cast(uidasBIGINT),20),ds;3)Bitmap标签数据同步Hologers
通过在Hologres中创建外表的方式将MaxCompute中的标签数据导入至Hologres。
通过在Hologres中创建外表的方式将MaxCompute中的人群数据导入至Hologres。
在Hologres中将进行画像分析。
--HologresSQLSELECT${label_alias}as"${label_name}",sum(rb_and_cardinality(t1.bitmap,t2.bitmap))as"人数"FROM(SELECTbucket,bitmapFROMpublic.holo_crowd_tableWHEREcrowd_id='${crowd_id}')ast1JOIN(SELECTfield_value,bucket,bitmapFROMpublic.holo_tableWHEREds='${label_ds}'ANDlabel_id='${label_id}')ast2ont1.bucket=t2.bucketGROUPBY${label_alias}说明:label\_alias最简单的方式是t2.field\_value;直接取构建的结果用来展示,复杂的则是要在代码层面做个映射关系,不同分级的中文含义。
1、用户识别码(UID)分桶设计:由于用户数量较大,决定在一个桶中放置多少用户变得尤为重要。业务应根据具体场景进行测试,确定每个桶的最佳用户数。一般桶的用户数越多,越耗费CU,速度可能有一定提升。
2、分析结果异步返回设计:虽然Bitmap加速后80%以上的场景都可以在10秒内返回,但对于可能产生大量桶的偏好类标签,可能会超过接口超时时长限制,因此需要设计一种有效的异步机制。如果初次查询未能返回结果,系统将返回相应的任务ID(taskid)。然后,通过taskid,交互侧可以进行轮询以获取结果。
3、构建任务调度设计:整个构建和同步过程都是耗时较长的任务,因此需要一个有效的调度机制。技术已经拥有一套基于有向无环图(DAG)的调度流程,在技术侧可以直接采用。
基于Bitmap的画像分析,75%的的比例在10秒之内可以出结果,个别由于数量级过大(例如几十亿人群规模,以及一些复杂的标签)会有一些长耗时的执行。
通过HologresRoaringBitmap的功能,我们技术平台实现了从原来的分钟级画像计算,到千亿级人群画像秒级分析体验,帮助业务查询效率提升几十倍,也进一步节约了计算资源。