Doris在用户画像人群业务的应用


欧阳利萍html

百度用户画像团队架构负责人web

基于用户画像进行人群定向是一种普遍的业务场景,在广告、增加等领域有广泛的应用。如何可以高效分析、规则筛选,特别是在超大规模的互联网业务场景,是一个有挑战性的技术问题。在这个分享里面,咱们会介绍一种基于Doris来实现海量用户tag下分析与圈选的高性能实现。sql



讲座分为三部份内容:apache

  • 用户画像群体服务的业务场景微信

  • 技术问题、思路与相关业界方案实现状况网络

  • 基于Doris的技术实现数据结构






1 用户画像群体服务的业务场景架构

1.1 画像业务分析场景

百度的用户画像是面向百度全产品线的基础数据和服务平台。并发

咱们会为包括百度凤巢、搜索、Feed等百度各条产品线提供服务,天天有着千亿级的离/在线的数据调用规模。app

随着业务的发展,咱们逐步造成了用户理解全流程的数据和服务,覆盖从多元数据的采集、大规模的数据挖掘、高性能的数据服务以及面向业务场景的解决方案。


在咱们的工做中,用户群体分析人群圈选是比较常见的需求,包括群体分析、业务报表、Geo检索、圈选等具体的场景。因为整个数据的规模比较大,同时业务对于时效性的要求比较高,在很多的业务中咱们采用基于Doris的方法来支持和实现。群体分析你们可能会比较熟悉,也就是对一个给定人群作人群报告和多维分析。业务报表也是常见的OLAP场景,对不少业务数据进行统计计算,Doris的基础能力可以很好的知足这些业务场景。



Geo检索你们可能不是那么熟悉,Doris在2019年先后集成了Google Geo的索引,使得对于基于地理位置的数据可以快速地进行查询、聚合操做。在一部分对于区域位置相关检索的领域,Doris可以发挥它分布式的优点,达到不错的应用效果。

咱们本身的应用测试是经过构建覆盖全北京的400万细粒度多层网格数据,去完成一个具体的随机的 0.1km2 以上的区域的群体计算。Doris处理 1 平方千米区域的群体数据的耗时在1.5秒左右,这对于不少的区域报表,像城市大屏、城市综治管理等场景,它是有很是大的应用空间的。




1.2 超大数据规模下的标签索引问题

基于用户标签的索引,是各大互联网公司应用最普遍的业务,也是咱们今天重点讨论的一个场景。

不管是基础数据团队仍是业务团队都会经过标签 tag 的挖掘来更好表达对用户的理解。咱们画像团队系统地构建了用户标签体系,但咱们的数据规模相对来讲更大一些。

这里有几个缘由:一个是整个产品线覆盖和流量规模,此外还有一些特殊状况,好比咱们的 id 规模远大于天然人的 id 规模,是一个数百亿级别的数据。

另一个方面,咱们从数据挖掘的层面创建了一个比较强、比较全面的画像标签体系,它的整个规模会比较大,人均的标签覆盖比较广。它的好处是能够灵活支撑应用,可是问题是在应用过程当中会产生一些规模上的问题。

基于这些标签,能够条件筛选的去构建人群,进而在用户推荐、广告定向、消息推送、用户增加等领域应用。

通常来讲这种业务有两个特色,一个是客户对标签的选择范围很是广,条件组合很复杂,业务灵活度很是高;另外一个是对计算效率,特别是对于人群圈选的数量,人群分析计算的时效要求很是高。计算越快,使用越灵活,越可以帮助客户找到他的目标人群。





2 技术问题、思路

2.1 早期基于离线计算的方法

早期咱们采用的是基于离线的计算方法,也就是用MapReduce来解决问题。这个方法的问题很是显而易见,灵活性差、计算成本很是高、时效是业务团队几乎不能忍受的,早期基本上是天级,最少也是小时级才能产出结果。


2.2 技术问题

咱们对问题进行了一个简单的分析,问题的核心仍是前面提到的——被计算的数据规模。

咱们目前是300亿——600亿的IO规模,标签数量2000+,因为标签下面还可能会有枚举值,因此最终会有大概300万左右的tag。对所有数据进行一个扫表操做就要花很是多的时间。

另外一个核心问题是,咱们以前的业务场景过于复杂,为了配合业务场景在选择技术方案是作了不少的让步——更多的考虑知足业务需求而非性能。因此早期在计算逻辑层面没有处理的特别好,整个计算效率是比较低的。

可是这一类需求在咱们的业务当中却展示的尤其强烈,咱们很是迫切的想解决性能和功能的问题。因此在调研了很是多相似业务的方案后,咱们提出了一种高性能标签索引的解决思路,而且考虑开发一套专用的系统来实现和解决相似的问题。


2.3 技术思路

(1)解决IO规模问题

原先的方法不管是基于MapReduce仍是其余相似的逻辑,核心的问题在于咱们要对全局数据进行遍历扫。由于咱们是以 uid 为 key 的一个正向的数据结构,对标签进行扫必需要扫全量。

这里咱们的解决办法是作倒排索引,以标签为 key 把 uid 做为value。这样构建一个反向索引以后,原来咱们是全表扫,如今变成只处理关注的标签,这样总体的IO规模会瞬间降低好几个数量级。

其次咱们要作一个计算加速的优化,这里面主要是逻辑的变化。把原来圈选的逻辑变成交并集的处理

在细节上须要作考虑两个问题:

一个是把原来标签的枚举变成二值化的 tag。

好比:标签球类运动,它的每个枚举值,就须要拆解为具体的 tag,如篮球、足球等。基于这个转化,能够把条件圈选变成交集、并集计算的组合。例如,选择喜欢篮球运动、不喜欢足球运动,就能够变成 tag-篮球 1,tag-足球 0 的交集。

另外一个是咱们有超过300万个 tag ,在对 tag 作倒排索引时存储空间会成为一个很是大的问题,因此须要进一步下降存储,提高计算效率。

咱们选择采用 Bitmap 来优化标签索引,用一个 bit 来标记一个 value,将用户做为整个 Bitmap 里的一个位,这样能够实如今存储上的空间节省。同时因为位运算在交并集上自然的优点,在计算上也能带来性能提高。

(2)加速计算过程

在解决计算规模问题时,核心的逻辑是用并行计算来加速过程。因为数据的 tag 是 key 构建的,尤为一些基础的标签的数据覆盖率很是高,有些能够达到90%以上,整个 Bitmap 会很是长。

这个状况下,对于一个百亿级的 uid 范围,bitmap 的 size 将会很是大,这些 bitmap 会成为计算平响,须要进一步对 bitmap 进行纵向的分桶,以加速计算,减小长尾。考虑 tag 数乘以分桶的状况,这是一个数量可观的分布式并行的储存与计算过程,对于分布式系统有着很高的要求,也是一种典型的 MPP 场景。

比较巧的是,在和 Doris 同窗的交流过程中,咱们得知 Doris 正在作类似的工做。Doris 的 MPP 架构和正在进行的 Bitmap 集成,恰好是咱们业务须要的能力。能够说是不谋而合。

咱们也调研了其余开源解决方案好比说 Kylin 和 Druid,Kylin 在这个场景下有必定的局限性,它须要预计算,这就带来了维度和空间的爆炸,而且不能知足咱们对细粒度数据的需求。Druid 在这方面能够知足咱们的需求,可是在一些特定使用场景下咱们是依赖Doris 的,因此咱们最终选择了 Doris





3 基于Doris的技术实现

3.1 Doris分布式查询引擎

结合业务场景,咱们将方案调整为基于Doris实现全套的标签索引服务。

Doris 采用的 MPP 架构很是简洁,由 FE 和 BE 完成从服务接入到数据存储、管理、计算的分布式服务。其中,FE 负责存储以及维护集群数据、接收、解析、查询、设计规划总体查询流程,BE 负责数据存储和具体的实施过程。FE 会根据用户的查询去生成一个完整的逻辑规划,进一步构建分布式的逻辑发给整个集群去执行。

在右边规划图中,由一个 BE 去执行的时候,须要经过 RPC 进行数据交换,不一样的计算方法和内容,交换的数据也不一样。


3.2 Bitmap在Doris的应用

Bitmap 一般做为 OLAP 系统和存储系统的索引,Doris 很早就集成了 Bitmap 来加速数据查询的过程。

如上图所示,右边是 Doris Bitmap 索引的数据结构。

和索引应用不一样,Bitmap 做为数据应用,能够解决明细数据的查询、交并集问题。咱们在使用的时候将 Bitmap 做为数据结构,直接使用 Bitmap 做为实际存储数据来解决明细数据查询和交并集计算的问题。

基于Doris,首先咱们经过离线的MR形式完成了标签 tag 的二值化和 uid 倒排(这里还包括对ID的顺序处理)。

而后咱们用 Bitmap 做为数据结构,Bitmap Union为聚合函数,采用Doris Load的方法完成了数据建库和数据Load,这个过程可能比较慢但很可行。

接下来,咱们须要把条件查询转变成交并集计算,对单个节点来讲,intersect_count / union_count 的方法 Doris 能够自动完成分布式的计算过程,实现已经 Bitmap 化的标签数据的聚合计算。

基于以上的逻辑,咱们只用了两周就完成了测试过程。


3.3 标签索引应用在Doris基础实现的问题

以上的方案在比较小的计算规模上能够获得计算结果,对于稍微复杂的计算场景,就出现了一些问题。

咱们作了一个测试,在300亿的 uid,平均标签数为300的状况下,可以完成不包含稠密 Bitmap 的 tag 进行6个标签的交集和并集的计算,但当咱们把条件 tag 换成稠密的 Bitmap 以后,用14个标签就已经超时了。(这里稠密的Bitmap指 tag 数据在全量用户 id 的覆盖率很是高的状况,而这种 tag 偏偏是咱们业务中最经常使用到的。)

除此以外还有一个功能问题,当时Doris还不支持批量ID导出。


3.4 标签索引应用在Doris基础实现的性能问题

结合 Doris 的计算过程,咱们分析认为问题的核心主要有两点。第一点在于 Bitmap 自己实现的逻辑,第二点在于在 Doris 中 Bitmap 分布式实现的问题。

通常来讲,32位 Bitmap 在压缩比和计算效率上有很好的平衡,可是64位的 Bitmap 的计算效率就相对比较差。画像的数据在百亿级别,因此须要用64位的 Bitmap ,那么计算效率就比较低。

第二个,当 Bitmap 基数比较大时,数据规模也比较大,网络磁盘和网络IO处理时间比较长。Doris 在计算过程当中须要 scan 数据后所有传输到顶层节点进行求交和求并运算,但本质上交并集计算是在单节点进行的,同时要通过网络IO以后才能进行处理,这都成为了影响性能的关键点。


3.5 性能解决方案

(1)Bitmap纵向切分建库

针对以上的问题,咱们提出了一种正交的Bitmap计算的UDAF解决办法。

咱们对 Bitmap 进行纵向的切分建库,如右图所示,咱们的出发点是减小或避免高32位的计算,而且进一步提高并发能力。

具体来说,首先咱们按照 uid 进行数据纵向切分,以 rid 范围进行分片,下降单个 Bitmap 的 size。这同时带来了一个好处,这种切分方式知足正交方式,不管在 tag 维度层面仍是在 id 范围层面,同一个分片内是能够相互独立的。基于这种正交关系,咱们进一步优化分布式计算的实现。


(2)分布式计算优化

首先在数据层面,咱们让相同 id 范围的数据(即便不一样 tag)也在相同的实例部署。在数据的交并集计算上,咱们让各个分片分别在各自的节点上完成计算,merge的是计算结果而不是原始数据。这样可让计算的节点数变多、实现并发,还能够在数据传输过程当中不进行全量传输,网络通讯的成本也降到最低。

右图所示是进行 count 计算时,在本地完成了 local 的交并集计算以后只须要把 count 值给出去,最后将不一样的 count 值 merge 就完成了整个计算过程。


3.5 性能测试

通过以上的处理,咱们的总体计算效率获得了很大的提高,小数据量的状况下获得了两个数量级的提高,在大数据量下咱们由不可能变成了可能

从上图中能够看出,性能变得更加可用,能够在秒级完成咱们的业务需求。


3.6 标签索引应用在Doris基础实现的功能问题

(1)数据灌库、建库

目前仍是基于以前的离线计算方式,这种方式效率不够高,可是引入新的解决方法——Enhanced Spark-based Load,这种方式如今还在测试,预计性能会有很是大的提高。

(2)批量ID导出

Doris 自身的 SQL API 没有支持亿级数据导出。结合业务场景 Doris 的同窗帮咱们想出了一种解决方法——经过修改现有的 select outfile 将 MysqlWriter 改写成 FileWriter,而且经过 Broker 把结果数据写到远端存储。这样就能够实现批量原始 id 的数据导出,知足咱们对细粒度用户数据的需求。





4 业务效果


  • 标签索引知足主要人群圈选业务场景

  • 人群圈选时效从天/小时级提高到秒级响应

  • 业务应用效率大幅度提高,支持更加灵活的业务应用

  • 在广告、增加等方向取得良好的业务效果




5 应用指南


咱们在今年8月已经将相关的代码和使用指南已经提交到 Apache Doris 的代码库,供你们分享使用:http://doris.incubator.apache.org/master/zh-CN/extending-doris/udf/contrib/udaf-orthogonal-bitmap-manual.html

这里须要有一个额外的编译过程来知足UDAF的应用:

最终使用的时候只须要写一个select BITMAP_COUNT 就能够快速获得须要的数据结果。


本文分享自微信公众号 - 小晨说数据(flink-spark)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索