25

快手 HBase 在千亿级用户特征数据分析中的应用与实践

 4 years ago
source link: https://www.tuicool.com/articles/eyayE3r
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

baABRrn.jpg!web

分享嘉宾:陈杨 快手

编辑整理: Hoh Xil

内容来源:BigData NoSQL 12th Meetup

出品社区: DataFun

注:欢迎转载,转载请注明出处。

快手建设 HBase 差不多有2年时间,在公司里面有比较丰富的应用场景:如短视频的存储、IM、直播里评论 feed 流等场景。本次只分享其中的一个应用场景:快手 HBase 在千亿级用户特征数据分析中的应用与实践。为什么分享这个 Topic?主要原因:对于大部分公司来说,这都是一个普适的场景,因为很普遍,所以可选择的分析引擎也非常多,但是目前直接用 HBase 这种分析用户特征的比较少,希望通过今天的分享,大家在将来遇到这种场景时, 可以给大家提供一个新的解决方案。

本次分享内容包括:

  • 业务需求及挑战:BitBase 引擎的初衷是什么;

  • BitBase 解决方案:在 HBase 基础上,BitBase 的架构是什么样;

  • 业务效果:在快手的实际应用场景中,效果如何;

  • 未来规划:中短期的规划。

业务需求及挑战

1. 业务需求

2iy2qmm.jpg!web

用一句话来概括业务需求:在千亿级日志中,选择任意维度,秒级计算7-90日留存。

如上图所示。左边是原始数据,可能跨90天,每一天的数据可以看作是一张 Hive 宽表,在逻辑上可以认为每行数据的 rowkey 是 userId(这里不严谨,userId 可能是重复的),需要通过90天的原始数据计算得到右边的表,它的横轴和纵轴都是日期,每个格子表示纵轴日期相对于横轴日期的留存率。

该需求的挑战:

  • 日志量大,千亿级;

  • 任意维度,如 city、sex、喜好等,需要选择任意多个维度,在这些维度下计算留存率;

  • 秒级计算,产品面向分析师,等待时间不能过长,最好在1-2秒。

2. 技术选型

BviYBjm.jpg!web

面对这些问题,我们当时的技术选型:

①  Hive,因为大部分数据可能是存在 Hive 里,可以直接写 SQL 计算,该方案不用做数据迁移和转换,但是时延可能是分钟到小时级别,因此否定了这个方案。

②  ES,通过原始数据做倒排索引,然后做一个类似计算 UV 的方式求解,但是在数据需要做精确去重的场景下,它的耗时比较大,需要秒到分钟级。

③  ClickHouse,ClickHouse 是一个比较合适的引擎,也是一个非常优秀的引擎,在业界被广泛应用于 APP 分析,比如漏斗,留存。但是在我们的测试的中,当机器数量比较少时 ( <10台 ),耗时依然在10秒以上。

立足于这种场景,是否存在其它解决方案,延迟可以做到2-3秒(复杂的场景10秒以下),同时支持任意维度组合?基于 HBase,结合业界简单/通用的技术, 我们设计并实现了 BitBase 解决方案,用很少的资源满足业务需求。

BitBase 解决方案

1. 数据模型

niEbAbQ.jpg!web

如上图所示,首先将原始数据的一列的某个值抽象成 bitmap(比特数组),举例:city=bj,city 是维度,bj (北京) 是维度值,抽象成 bitmap 值就是10100,表示第0个用户在 bj,第1个用户不在北京,依次类推。然后将多维度之间的组合转换为 bitmap 计算:bitmap 之间做与、或、非、异或,举例:比如在北京的用户,且兴趣是篮球,这样的用户有多少个,就转换为图中所示的两个 bitmap 做与运算,得到橙色的 bitmap,最后,再对 bitmap 做 count 运算。count 表示统计“1”的个数,list 是列举“1”所在的数组 index,业务上表示 userId。

2. BitBase 架构

e2yQVjM.jpg!web

整个 BitBase 架构包括五部分:

  • 数据存储: 主要存储两类数据,一类数据是 bitmap 索引和数据,另一类是转换字典的归档文件(见后面描述)。

  • 数据转换: 有两种方式,第一种是通过 mrjob 转换,第二种是在线计算或导入;

  • 数据计算: 负责计算和调度,并把 IO 数据计算结果返回给 Client;

  • Client: 站在业务的角度,把它们的业务逻辑分装成一个个业务的接口;

  • ZK: 整个系统是一个分布式的服务,用 ZK 做管理。

3. 存储模块

NZfQ7vA.jpg!web

用数据存储设计的核心目的是让计算更快。

如上图,左边为一天的原始数据,包括多个 table,通过 mrjob 或者 rpc 的方式转换成中间的 bitmap。

bitmap 分为两部分,第一部分为 meta 信息(橙色部分),第二部分是 data 信息:

  • Meta 信息唯一定位一个 bitmap,db 可以认为是 hive 中的 db,table 也可以认为是 hive 中的 table,event 表示维度 (如:城市),eventv 表示维度值 (如:bj),entity 表示 userId(也可能是 photoId),version 表示版本。

  • BitmapData 从物理上讲是一个比特数组,把比特数组按照一定的大小进行切块:b1,b2,b3,...,bn,从而实现分块存储,分块计算。

最后把 bitmap 存在 HBase 的3张表中: 两张核心表和一张辅助表。

  • BitmapMeta, 保存 bitmap 的 meta 信息和一些 block 索引信息。

  • BlockData, 直接保存 bitmap block 数据。

  • BlockMeta,保存 block 的 meta 信息,起辅助作用。

4. 计算模块

aqEFVri.jpg!web

一个完整的计算流程涉及到三个组件:BitBase Client、BitBase Server 和 HBase regionServer。

①  BitBase Client 首先把业务的需求封装成计算表达式,然后把计算表达式发给 BitBase Server;

②  BitBaseServe 接收到请求后,从 BitmapMeta 表中查询 Block 索引,然后根据索引将表达式切分为 n 个子表达式;

③  如果所有 bitmap 的 db 相同,则走 coprocessor 路由,否则按照数据亲和性,将 block 计算分发到其它 bitbaseServer 中。

④  根据第3步的调度策略,分两条不同的路径计算 block 表达式

⑤  BitBase Server 聚合 block 计算表达式的结果,然后返回给 BitBase Client。

两种计算方式的对比:

  • 非本地计算,解决跨 db 计算的需求,它主要的瓶颈在于网卡和 GC。

  • 本地计算,解决同 db 计算的需求,它主要的瓶颈在 CPU 和 GC 上。整体上看本地计算的性能比非本地计算的性能提高3-5倍,所以要尽量采用本地计算方式。

5. DeviceId 问题

2I7niq3.jpg!web

在引入 Bitmap 数据模型之后,我们隐含的也引入了一个非常大的问题:无法支持 deviceId。要支持 deviceId,首先需要将 deviceId 转化为数字类型,并且转换之后的 DeviceIdIndex 必须要满足四个条件:

①  连续:deviceIdIndex 如果存在空洞,会降低压缩效率,同时 Block 数量会增加,计算复杂度相应增加,最终计算变慢;

②  一致:deviceId 和 deviceIdIndex 必须是一一对应的,否则计算结果不准确;

③  反解:根据 deviceIdIndex 能够准确、快速地反解成原始的 deviceId;

④  转换快:在亿级数据规模下,deviceId 转化为 deviceIdIndex 的过程不能太长。

6. DeviceId 方案

连续、一致、支持反解:

JN3qEvN.jpg!web

如何保证连续、一致、支持反解?解决方案非常简单,利用 HBase 实现两阶段提交协议。如上图中间实线部分所示,定义 deviceId 到 deviceIdIndex 的映射为字典。第一张表存储字典的 meta 信息;第二张表存储 index 到 deviceId 的映射;第三张表存储 deviceId 到 index 的映射。

生成 Index 的过程。举例说明, 假设我们已经生成了 1w  个 deviceId 映射,那么此时 f:max=1 w ,现在将新生成 1k 条映射:

① 将 f:nextMax=f:max+1k=1.1w;

② 写 Index 到 deviceId 的反向映射表,1k 条;

③ 写 deviceId 到 Index 的正向映射表,1k 条;

④ 把 f:max=f:nextMax=1.1w 更新到 meta 表,生成过程结束。

如果在生成过程中出现异常或服务器宕机,则执行回滚流程:

① 如果我们检测到 f:nextMax 不等于 f:max(f:nextMax>f:max),则从表2中查询 max 到 nextMax 的数据,从表3中删掉相应的 deviceId 到 index 的映射记录;

② 再删掉表2中相应的 index 到 deviceId 的记录;

③ 最后把 f:nextMax=f:max,从而实现数据100%一致。

用 HBase 实现两阶段提交协议要求 index 生成流程和回滚流程一定是单线程的,从而出现性能瓶颈,所以 BitBase 设计了归档流程,以支持快速转换(见后面的描述)。Meta 表中有两个字段,如果发现新产生的数据大于 f:archive_num 就发起归档,把表3中的新数据直接写到 HDFS 中 archive_path 目录下。

快速转化:

iiUrYbb.jpg!web

这里我们用到了 MRjob 中的 Join:

① 同时输入原始数据和字典归档数据,在 MRjob 中根据 deviceId 做 join;

② 判断 deviceId 是否 join 成功;

③ 如果成功了,直接写 hdfs,这样就得到了转化后的数据;

④ 如果 join 失败,直接请求单实例 BitBase Master,BitBase Master 通过两阶段提交协议生成新的映射;

⑤ 然后返回给 join task 执行替换 deviceId;

⑥ 把转换后的数据写入 hdfs。

反解的过程很简单,直接多并发读取 HBase。

业务效果

EVBR7fa.jpg!web

如上图所示,第一个图是,2维度,不同时间跨度计算留存的时间延迟,第2个图是15日留存在不同维度上的时延,时延并不会随着维度的增长而增长,原因是维度越多,表达式中可能不需要计算的 block 块也越多。

VvMbqeF.jpg!web

如上图所示,BitBase 可以应在 app 分析,用户增长,广告 DMP,用户画像等多个业务场景中。

未来规划

EziEjmB.jpg!web

根据现在面临的业务场景,BitBase 后续会在多个方面做优化。支持实时聚合,在一些业务场景下,如运营效果监测,导入时效需要 <5min,BitBase 需要支持实时聚合;支持 SQL 查询,目前只支持 api 的接入方式,在一些简单场景下比较复杂;开源,希望通过开源,和大家一起挖掘 BitBase 的业务场景。

FbMnMzN.jpg!web

嘉宾介绍

陈杨,快手大数据高级研发工程师。负责快手HBase以及相关生态组件的维护与研发。

——END——

配套 PPT 下载:

请关注社区公众号,后台回复【 BitBase

文章推荐:

快手 Druid 精确去重的设计和实现

Apache Doris : 一个开源 MPP 数据库的架构与实践

关于 DataFun:

DataFun 定位于最实用的数据智能平台,主要形式为线下的深度沙龙、线上的内容整理。希望将工业界专家在各自场景下的实践经验,通过 DataFun 的平台传播和扩散,对即将或已经开始相关尝试的同学有启发和借鉴。

DataFun 的愿景是:为大数据、人工智能从业者和爱好者打造一个分享、交流、学习、成长的平台,让数据科学领域的知识和经验更好的传播和落地产生价值。

DataFun 成立至今,已经成功在全国范围内举办数十场线下技术沙龙,有超过三百位的业内专家参与分享,聚集了数万大数据、算法相关领域从业者。

nQry6nn.jpg!web

点下「在看」,给文章盖个戳吧! :point_down:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK