写点什么

每日生产万亿消息数据入库,腾讯如何突破大数据分析架构瓶颈

  • 2018-11-20
  • 本文字数:10469 字

    阅读完需:约 34 分钟

每日生产万亿消息数据入库,腾讯如何突破大数据分析架构瓶颈

背景介绍

对于腾讯庞大的大数据分析业务,几千台的 Hadoop 集群,近百 P 级的存储总量,每日产生万亿的消息数据入库,需要针对几十亿 IMEI 手机设备去重,并关联数千亿的历史全表,进行曝光、点击、PV、UV、日活、新增、留存等统计指标分析,当前所有业务的 ETL 清洗、统计计算、用户画像都全部依赖离线 m/r 和 Hive SQL,给集群造成很大压力,系统负载高任务积压重,计算耗时久业务响应慢(t+1),难以及时反馈市场信息的变化,不仅是技术上的巨大挑战,同时业务的迅速增长变化也在挑战着当前技术团队的工作模式和流程。如何突破现有大数据分析架构瓶颈?


本文内容将带来腾讯大数据技术的新发展和架构实践,介绍基于自研 bitmap 技术的大数据系统“锋刃”,以及 OLAP 全新驱动模式的架构战略,真正做到秒级实时查看每分钟指标、全维度的用户 OLAP 自助分析、闭环的动态运营体系。


讲锋刃大数据方案之前,我们先整体看看大数据平台架构,有诸形于内必形于外,很多局部状况的问题,需要从整体来看,为此,我们按照集群状况,典型业务流程和数据流、系统架构瓶颈点的思路顺序,以表知里的进行一下梳理。

一、集群状况的反馈

当前 Hadoop 集群系统性能繁忙(3 大区域 7 大机房),1000 多存储机器对应 4000 多计算机器,cpu 平均值 70%-80%(晚 20 点到 0 点较低),5 分钟负载很高,任务积压重;ech1 几百兆,峰值几个 g;磁盘 io 约几百兆,峰值几 g,读写 iops3000。存储计算比为 1:2,业务 job 还在增长之势,1:3 到 1:4 将达到集群瓶颈。


很多时候我们看到集群繁忙,只当作运维问题去解决,扩容集群机器,调整机房部署,优化调度能力和虚拟化,增强任务监控管理等。却很少关心集群上跑的都是些什么任务,为什么会给集群造成这么大的压力,我们接下来通过梳理业务流程和数据流来搞清楚这个问题。

二、典型业务流程和数据流

手机浏览器业务场景典型流程:从手机浏览器的资讯日志数据,统计每板块的 PV,并挖掘用户浏览咨讯的内容提取标签,并计算标签权重,进行推荐,再将推荐结果反馈到日志。


三、贯穿业务场景的数据流

多份业务 log 和产品如灯塔 sdk 产生多份数据日志,分别有各自的通道和 hdfs 数据模型,对集群存储和计算有很大重复,也造成各自数据的不完整,目前尚未在“通道采集—基础数据—集市数据——高级画像”数据流链路上形成统一数据模型,这样即能优化节省资源,又能数据建模标准化,所有统计计算和算法挖掘都基于统一数据标准进行,上层可以提供大量工具化用户产品。


四、系统架构瓶颈全链路分析

综上所述,我们通过对集群、采集、通道、统计、存储、数据治理、idc、业务场景的全链路架构分析,归纳出以下瓶颈点:


  1. Hadoop 集群的繁忙压力

  2. 所有业务全部依赖离线 m/r 计算和 Hive SQL

  3. log 采集的大量重复内容

  4. MQ 集群每日消息总量万亿但无法提供内容过滤

  5. 冷热存储、短期存储(天内)、长期存储(T+1,周、月、年)混一起

  6. 做到小时和分钟级别统计很难。

  7. 没有一个统一精简的数据模型形成标准。

  8. 业务的存储和计算还在迅速增长…


但是不可能所有的架构瓶颈都能在短时间内进行优化改进,我们需要寻找一个最合适的切入点,先解决最迫切的问题。

五、迁入实时计算的优化和问题

(一)从业务流程和数据处理的逻辑,反思当前架构和处理方式:

1、采集源头的 log 生成:如应用宝产生 6000 多 log,其中 30%-40% 的内容是重叠(设备信息、身份信息等),开发人员根据需要自定义新的 log,每个 log 产生后续一系列存储表,以及新的工作流 job,不断累加。对于每个 log,有的超过 100 个字段,支持很多种统计任务,但是每种统计只需要其中很少字段即可完成。


(1)、Log 进行重新梳理和合并,减少冗余,制定 log 规则


(2)、考虑从源头进行 log 梳理和分流,以统计业务维度接收局部消息内容:



2、通过大量 hdfs 存储表实现数据流处理:以手机浏览器业务,每个 log 表会产生多个清洗结果表,多张清洗结果表汇合清洗统计表,完成统计计算后,还需要汇合多张统计结果表,形成通过大量的 hdfs 中间存储表,来实现统计和集市的数据处理逻辑。如果考虑用实时流取代存储表处理流,可以带来很大的资源节省和效率提升:



3、当前离线处理方式,以灯塔为例,每 10 分钟接收 MQ 通道的日志数据,在 HDFS 建立一个分区,一天共 144 个分区,每个分区建立 3600 个几 K 到 10M 的小文件不等,再提交 144 个离线 JOB 去执行清洗任务,产生 1500 个解析表,再按照小时、天、月建立统计统计任务,反复关联全表热表操作,完成新增用户等典型统计。离线处理方式计算和磁盘耗用严重,解决 1 天内的实时需求难以满足。除灯塔外,其他的业务也按照这种方式源源不断产生大量的离线任务进行统计,除计算外还会产生大量数据存储冗余,现在我们终于明白集群为什么如此繁忙的症结所在了。

(二)迁入实时计算进行优化的考虑:

1、经过分析了灯塔、应用宝、手机浏览器和手机管家,业务的相似主线模式如下,更适合实时处理;



2、清洗部分实时处理 DEMO 验证:相对于离线计算 MAP/REDUCE 的时间消耗换算,耗用机器数从 84 台降低到 15 台 m10,完成了 90% 的数据量进行流式清洗,包括:从 kafka 拉数据 ->解包 ->byte2string->清洗 ->string2byte->,5 分钟处理 10 亿消息数据,333w/s,接近 mq 纯拉取消费的 360w/s;


3、清洗转换步骤,采用实时流处理架构如 Storm,通过 spout 从 MQ 获取输入流,自定义多个 bolt 并行处理输入流,再依此组合设计;



4、业务迁移计划,以灯塔广告监测 CASE 为切入逐步安排计划迁移。

(三)实时计算框架选型问题:

其实我们的技术团队当时也考虑过通过实时计算来优化,但是基于传统流处理实时计算方案 Storm、Spark Streaming、Flink 框架进行实施时,面临一系例问题阻碍,导致无法大范围推行:


当时团队现状:Storm 和 Spark Streaming 研发支持和运维能力较成熟,原始 Flink 还需要优化,尚不具备直接大规模工程化实施的条件。


  1. Storm 的算子封装和开发成本较大,但是能很好解决 1 分钟到 1 小时实时计算和离线资源释放,SQL 支持弱,业务分析团队更习惯写 SQL 做清洗和统计。

  2. Spark Streaming 开发成本低,能解决 5 分钟 10 分钟实时批量计算,但是 1 小时计算无法释放离线资源,统计 1 分钟级结果会产生大量调度任务。

  3. Flink 提供流式和批量结合的实时处理和完善 SQL 支持,适合完成清洗和 count 计算,但其有限时间窗口并不太适合大批量用户去重和统计。

六、锋刃大数据架构方案

到目前为止,我们需要寻找一种新的大数据架构方案,针对海量大数据的实时统计场景进行专门设计,得到更先进的解决办法。我们把业务场景简化一下如下表述,按照因果关系,我们通过手机设备获取到一些 app 维度的 log 数据,经过大数据平台的统计处理,最后得到用户相关的结果和一些 count 类结果(pv,uv, 金额,数量等),现在我们想在内存中按照维度组合来实时计算这些结果,削峰填谷把离线累积的数据统计变成每分钟实时流处理。


(一)BitMap 位存储和位计算

为了解决海量用户的去重问题,我们发现使用 bitmap 有两个非常显著的优势:位存储占用空间低,位计算效率高。


1、将需要做统计计算的 id 转换成数字序号,每个只占 1 个 bit,对于 20 亿的用户 id,只需要 20 亿 bit 约 238m 大小,压缩后占用空间更小,最少只要 200k;



2、通过单个 bitmap 可以完成去重操作,通过多个 bitmap 的且、或、异或、反等位操作可以完成日活、月活、小时分钟活跃、重度用户、新增用户、用户流向等绝大部分的统计计算,而且能在单机毫秒级完成,真正做到实时计算出结果,同比 Hadoop/Hive 离线计算执行“select distinct count…from…groupby join…”类似 SQL 的方式统计,往往需要几百台机器,耗用 30 分钟才能完成,对比非常悬殊,而且容易形成大量 SQL 任务调度和大表 join 给集群带来繁重压力。

(二)BitMap 聚合计算

通过多个不同维度的 bitmap 聚合计算,来解决离线统计里复杂的 join 问题,几乎可以涵盖所有用户统计相关的场景:


  1. 去重用户:求 1 的总数

  2. 活跃用户: 取或 bitmap1 | bitmap2

  3. 非活跃用户:取反:~bitmap1

  4. 重度用户:取且:Bitmap1 & bitmap2

  5. 留存用户:取且再求百分比:Bitmap1 & Bitmap2 相对于 Bitmap1 的百分比

  6. 新增用户:取或加异或:(Bitmap1 | bitmap2)^bitmap1

  7. 流失用户: Bitmap1 相对于 bitmap2 的新增用户

  8. 用户流向:app1time1 的流失用户 &app2time2

  9. 多种指标组合:Bitmap1 & bitmap2 & bitmap3 &…

  10. 等等



按照不同维度生成用户 bitmap 后,会得到如下面表格描述的数据结构:



我们可以看到,这个数据结构是个大的 0,1 矩阵,每一行代表某维度取值的用户 bitmap,把 1 累计可以求的此维度取值的用户指标,比如 hw 机型有多少用户在使用。每一列实际上可以获取到该用户的画像,比如 u6 用户用 oppo 机型、经常在北京和深圳等等,维度越多,画像信息越详细。另外,全盘用户的矩阵结构还有更深远的意义,我们在机器学习推荐中,基于特征处理后的 01 矩阵,可以完成大量的算法训练。


实际上,bitmap 的维度组合还有一些复杂性问题需要权衡,比如维度 A(共 10 个取值) 和维度 B(共 10 个取值),如果聚合 AB,有两种方式:


  1. 第 1 种,An&Bn,共 10+10=20 个 bitmap;

  2. 第 2 种,An_Bn,共 10*10=100 个 bitmap。


第 1 种存在数据叠加的影响,第 2 种不存在;


第 1 种消耗更少的空间,第 2 种消耗更多空间,但是根据业务实际数据出现建立 bitmap,实际占用空间小于理论组合全部值(比如 mi_kashi 不存在)。

(三) Bitmap 压缩分析
  1. 对于 bitmap 数量很多的场景,压缩有利于节省大量空间,对于 20 亿的用户 id,需要 20 亿 bit 约 238m 大小,压缩后占用空间最少只要 200k。

  2. 按照灯塔当前业务流量,42 亿范围的 id 不会全部来,去重后 1-2 亿进入 bitmap,按照 2:42 的数据分布,压缩后还是能省很多空间。

  3. 如果业务流量单位时间内(10 秒),42 亿用户全部来或者来 30 多亿,这时 bitmap 大部分为 1,压缩率反而很高,空间耗用不大。反而,对于只来 10-20 亿去重用户,这是要面临极端最坏的情况,数据分布广且稀疏,压缩有限,空间耗用很大。

  4. 不同的压缩算法压缩率和耗时成反比,考虑实时性和空间节省,选用压缩率和耗时比较平衡的 gzip 压缩。

(四)流式处理 +Bitmap 实时计算框架

将离线批量处理改成消息流式实时处理,并按照上面基于 bitmap 做去重和聚合的思路,我们得到下面新的架构:借助 flink 的 SQL 能力做清洗逻辑,并提供基于 SQL 的去重和统计 udf 的封装给到业务分析人员使用,构建一个分布式的 bitmap 集群服务来提供 bitmap 的计算引擎支持,统计结果的数据实时写到数据库里提供报表展示。



注意到,上面的架构里增加来一个 ID 查询服务的模块,它用来负责将手机 IMEI 号在线查询转换为数字 ID。


1、初始化:通过离线任务,按照最后活跃时间初始化用户 ID 的数字序号,很久没来的用户放前面,最近的用户放后面,新增的用户在后面加 1,这样直接从 bitmap 的数字 ID 范围知道是大致什么时间的用户,目前约 50 亿范围的用户 id,除去虚假用户和僵尸用户,还有 20 亿左右正常用户。结果:仅通过数字序号可以区别最近的用户还是很久以前的。


2、运行时:



未来:手机设备上,灯塔 sdk 直接携带设备 ID 的数字序号进入通道,逐步减少 id 查询,也就是说,未来对市场上几十亿手机设备,腾讯都能有一个除 imei 外自己的数字编号,这样会极大提升后台的大数据统计分析能力。

(五)BitMap 的空间耗用

1、大范围数字的空间浪费问题,如果不分区,一个值为 20 亿的数字需要耗用 238m 的空间;



2、分区 bitmap 的优势和问题,对于数字最大范围为 20 亿,按照不同的大小分区如下:如果每个分区很大,那么少量分布均匀的数字很容易占满所有分区;如果每个分区很小,分区数(key 的数量)就很多,key 的空间开销也很大。那么如何做到最优的空间消耗呢?



3、RoaringBitmap 的核心原理和不足:


RoaringBitmap(官网地址论文地址)是 Druid、Spark、Hive 等很多大数据框架依赖的 bitmap 核心组件,我们先看看它是怎么做到空间优化的。


RoaringBitmap 将一个整型数字拆分成高低 2 个短整型,并共用高位做 key,可以知道最大分区为 65535,低位做 value,可以用一个 short[][] 来存储,相同 key 的 value 存储在同一个 short[] 里,进行二分查找去重,当 value 的数量到达 4096 时,空间消耗已经等同于一个长度为 65535 的 bitmap,这时进行 bitmap 转换。 RoaringBitmap 在理论上通过高低分位成两个 short 类型数字,从而有效节省数据量小时的空间开销,并在数据增长到临界点 4096 时转换成 bitmap,数据量大时不再增长空间开销。



但是 RoaringBitmap 在落地的实现和应用中仍然通常在面临以下问题,不能做到性能和空间最优:


  • 高低分位后,实际上形成一个 65535*4096 的固定分区,对不同的数据特点,不能灵活设置分区大小和分区数量以满足不同数据范围和不同增长幅度的场景需求;

  • 在其 java 的实现版本里,由于 short 数组的动态变长,产生大量的无用对象不能及时垃圾回收(gc),而且只有当每个分区抵达 4096 数量时才能转为 bitmap 停止内存增长,容易导致在分区均匀情况下接近 4096 的时候空间开销很大,这时 bitmap 的数量很少,而 65535 个 short[] 动态增长产生的大量垃圾内存,其实际空间消耗已经远远超出理论的预估值。

  • 耗时慢,由于二分查找去重需要进行数组排序,会产生额外的性能消耗,特别是数据量低于 5000 万时,二分查找的性能并不比线性查找有优势,反而耗时更多。当数据量很大时,数组结构已经转成 bitmap,此时二分查找已经不再起作用。


4、原创实现的高效 ArrayBitmap


为了克服数据量小而且稀疏时导致的 bitmap 空间浪费问题,经过实践摸索寻找到一种动态增长的分桶数组结合 bitmap 数据结构的新设计方案来解决,经过大量测试证明,相对于 RoaringBitmap 有更好的性能和更优的内存空间消耗。



性能测试对比:


经过和 roaring bitmap 不同数据大小的测试对比(20 亿范围随机),情况如下:


  • 10 万、50 万、100 万、500 万、1000 万数据范围:内存占用略同于 roaring bitmap,但耗时只有一半;

  • 5000 万数据:由于超过 3000 万转 bitmap 存在拷贝空间耗用,内存占用大于 roaring bitmap,但是耗时更低;

  • 1 亿数据:内存占用和 roaring bitmap 接近,但是耗时只有三分之一。

  • 2 亿及以上数据:内存占用低于 roaring bitmap,耗时只有四分之一。


为了方便读者理解上面的思想,作者抽取出了两个简化的 java 实现类供参考,CoolBitSet.java 实现了 bitmap 的所有操作,CoolBitMap.java 是集成了数组和 bitmap 存储的高级结构,可在附件下载。

(六)锋刃大数据平台的建立

在成功解决了以上 bitmap 的各种问题后,经过 1 年多的建设,基于流式处理结合 bitmap 技术,从最开始的架构方案和程序 demo,已经实施落地为完整的大数据计算系统“锋刃” ,系统边界不仅解决实时计算,还包括离线提速和 OLAP,和当前数据工厂( Hadoop+Hive )互补,并且作为平台提供 bitmap 结构的文件存储,以及 OLAP 的大数据分析系统。PCG 运营数据应用框架团队提供锋刃平台开发和场景实施支持。

七、业务场景实施及架构升级

(一)腾讯灯塔实时统计上线

腾讯灯塔产品介绍:


腾讯灯塔是基于腾讯海量大数据开发的移动应用智能数据分析平台,聚焦数据驱动用户增长,为业务提供分析云与营销云服务。提供包括应用分析、广告效果监测、广告渠道反作弊、DMP 标签、市场指数等全链路大数据运营服务。腾讯灯塔秉承独立第三方的数据服务理念,去伪存真,指引有价值的增长。目前日均处理 4000 亿 + 日志,覆盖 MAU 13 亿,积累 7 大类,1000+ 标签。


产品官网:beacon.qq.com


1、灯塔实时计算经历“实时清洗上线—实时统计开发实施—试运行 1 个月—故障演练”共 3 个月,目前已经全量上线,所有产品可以查看一维 1 分钟和 10 分钟到实时新增、启动用户、启动次数。当前运行状况正常。



2、确定了实时系统服务保障量化指标,保证实时查看结果,对延迟情况保障:平均延时不超过 5 分钟,异常延时(版本更新重启等)不超过 30 分钟,超过 30 分钟属故障。vip 产品(1 分钟,10 分钟,日)保证和离线统计结果偏差不超过万分之五,长尾产品结果偏差不超过千分之五。


3、数据核对情况:以 10 分钟为标准,目前实时计算结果和离线统计结果核对一致。1 分钟离线没有统计,日统计离线有策略补充基准不一样,经过和灯塔业务确认,统一了核对结果。


资源耗用情况:


约 35 台机器(去重服务:6 台 m10,flink:11 台 m10,去重 dcache:4 台 m10 共 200g,id server:10 台 docker 合计 1 台 m10,id server dcache:10 台 m10+3ts80)。

(二)腾讯某安全产品场景离线提速上线
  1. 需求:当前离线 hive 计算每日 25 亿数量大 app 的卸载留存很难算出,复杂任务计算耗时从早上 8 点到晚上 11 点。

  2. 方案:现改用 bitmap 方案对 1200 个 app 进行优化提速,按 app_ 渠道 _ 日划分为 12 万个 bitmap 进行聚合计算。

  3. 效果:现统计留存卸载的耗时为,日 10 秒,周 20 秒,月 1-2 分钟(90 个 bitmap 聚合)

  4. 耗用资源:20 台机器(flink2 台、去重服务 7 台、dcache10 台(400g)、id 查询 1 台)


目前已经上线一期、二期。

(三)腾讯某大数据分析产品离线分析架构升级

需求:当前离线 hive 跑 3000 亿全表 join1000 亿日表耗时 7 小时以上,难以满足模型频繁验证。


方案:3000 亿全表按照 app 维度理论生成 3000 万的 bitmap(其中用于统计的数量在 100 以上有 200 万),1000 亿日表用于统计的数量 100 以上的有 48 万,20 亿用户大盘表生成 1 个 bitmap,通过三类 bitmap 求新增并更新历史全表和大盘用户表。


(四)ABTest 实时数据分析平台

1、ABTest 的应用场景可以分为两大类型:


(1)、算法类:浏览器资讯、广告、搜索、推送


(2)、运营活动:浏览器框架改版、浏览器 vivo 装机新用户推送、应用宝活动类


2、ABTest 需求:


为了衡量算法投放前后或者是运营行为活动前后的效果,我们需要实时计算下述指标及综合指标的前后变化,并且通过用户标签(搜索类、看资讯类、点快链类、无行为类)划分人群来分析。


(1)、PV,UV,CTR;活跃,留存,新增,收入… 等实时/离线指标提升


(2)、模型量化计算综合提升


如下图,需要通过实时计算将表格内的统计指标完成:



3、Abtest 系统架构方案:



4、ABtest 实时数据分析平台上线


之前几个小时才能看到线上数据,现在只要五分钟!


实时数据能让我们能更快的看到实验数据,及时发现并下线异常实验。同时也能实时监控实验,及大盘核心指标,发现异常数据。更快发现问题就能更及时解决问题,从而降低异常对线上用户的的影响。


(五)业务实施推动架构升级

在实施上线以上实时统计、离线加速的业务场景,业务系统获得了高性能的同时,也暴露了在高可用性和高可靠性的某些不足,为此,也推动着锋刃实施团队进行自身的架构升级。


1、首先 flink 的清洗和去重改造成基于消息通道的生产消费模式,借助消息 offset 消费位可以更准确的故障恢复消费。


2、增加配置平台工具化方便业务配置自己的清洗逻辑、统计逻辑、聚合逻辑等。



3、我们发现,锋刃系统大部分的时间精力耗在上面的虚线框内,实现一个分布式的 bitmap 计算引擎、内存结构、及持久化存储上,以及稳定性保障上。将 bitmap 引擎迁移到部门 kv 存储产品 decache 和 bdb 上,并提供专门的热备、故障恢复、冷热切换、内存管理、分布式扩容等特性。这样锋刃复杂繁重的去重服务模块就简化成一个代理模块,可以更专注在业务需求的满足上。如下图:


八、OLAP 的愿景目标

我们的大数据统计需求其实可以归纳为两大类型:


  1. 关键维度的实时监控:适合少量关键维度比如 app 的去重用户、新增用户指标监控,周期性强,每分钟每天都需要统计输出。

  2. 所有维度的 OLAP 查询:适合业务的自定义排查分析,比如一次促销活动后,新增用户指标上去了,业务人员想通过地区、版本、版面栏目、动作等多种维度信息分析新增用户的构成,这是一种非周期性的排查分析需求。之前这样的特定需求都是业务方提交给数据分析人员专门写 hive 离线任务去完成。如果我们的大数据 OLAP 能力足够强大,可以让业务和产品人员完成所有维度的自定义查询,而且能在 5 秒内接近实时得到查询结果。可以很大提升我们的大数据统计效率和满足业务的灵活多样型,同时这样我们的数据分析人员也可以从繁琐的统计工作中得到释放,去转型做模型分析。


总的来说,做到让用户“关键维度自助看实时监控、所有维度分析自助 OLAP”,彻底解放我们的技术人员,这是我们想通过技术手段实现的愿景。


锋刃系统可以很好满足第 1 点的关键维度实时监控,但是要支持所有维度的统计,会产生大量的维度组合生成的 bitmap,并不适合走实时内存处理,并且高度灵活的根据维度取值来自定义查询,需要增加维度列式存储和索引设计。锋刃系统接下来需要在设计上增强对 OLAP 能力的满足。


我们先看看以 Druid 为代表的大数据 OLAP 技术的主要设计原理。

(一)Druid 的主要原理


简言之,Druid 的设计原理可以通过上述步骤归纳:


1、提出 rowid、时间戳、维度(多个)、指标(多个)的 OLAP 数据模型,并按列压缩存储,导入明细数据时设置 rollup 为 true 可以实现自动上钻合并,比如点击数累加。


2、在数据导入时,进行预计算,根据维度取值生成 rowid 的 bitmap 索引,而锋刃系统则是根据业务的特点,基于手机用户(IMEI)生成 bitmap 索引,这是两者的本质区别。


3 和 4、当执行带维度条件的 SQL 语句时,将 gd 和 1.1 对应的 bitmap 做聚合后得到关联的 rowid


5、通过关联的 rowid 找到列存储对应的指标点击数,进行累加得到最后结果


由于列存储和 bitmap 索引机制的高效性,Druid 不需要遍历整个数据集也不需要读取整行数据就能接近实时的计算出结果。


但是 Druid 在解决海量用户精确去重存在以下不足:


  1. 由于 Druid 的指标只能是数字,IMEI 无法当作指标,只能当作维度,几十亿 imei 会产生几十亿的 bitmap 索引,对内存会产生压力导致益出风险;

  2. Druid 是按行号建立 bitmap 索引,只能做根据维度取值的关联,找出关联行,但是 bitmap 索引不做 IMEI 去重。去重只能通过常规的 distinct 方法完成,对于几十亿的 IMEI 去重耗时长,容易超时。


Druid 要保证统计高精确性,必须要以明细存储,要牺牲导入时做聚合处理,增加查询时的处理压力。

(二)Druid、锋刃、Impala 各自适用场景
  1. Druid 最擅长解决“点击数/下载数”这样的指标,并且维度取值不是太大的业务场景;解决几十亿 IMEI 统计场景比较吃力,需要约束业务范围和数据量,按 app 和业务分类分表,针对不同业务特定分析。但是对于含有历史新增 imei 去重的 OLAP、以及多宽表关联仍然不太合适。

  2. 如前面提到的,锋刃当前适合解决预先定义的关键维度的实时统计和离线统计,是针对 IMEI 场景的高清确性的,但是设计上还不能覆盖所有维度的自定义 OLAP。

  3. Impala 适合解决数据范围不大的集群内存能覆盖的业务场景,超出内存限制性能会直线下降。

(三)统一的 OLAP 架构方案

如果在 OLAP 架构上没有统一规划,完全由各业务团队自由搭建,就会形成基于 Druid,Impala,Kudu,Kylin 等各式各样框架的方案解决各自业务小范围需求的局面,造成功能重叠及人员浪费,而且长期来看业务团队自身也不具备强大的运维能力。如果我们完全自研一套 OLAP 系统,比如在锋刃上实现自研 rowid 反向索引、分布式节点存储、查询、任务调度等 Druid 的功能,到最后测试稳定可运行,也需要耗费很久时间,业务团队面临用户压力,没有足够的耐心等待。


所以我们在保持自研能力的同时,也在构思可以用于马上满足业务需求的架构集成方案,把锋刃和 druid 的优势整合进来,虽然底层设计没打通,但是通过上层的集成和封装能得到一套统一的 OLAP 架构方案。


1、Cube 模型归纳


经过思考,首先架构方案需要满足一个 cube 的索引模型,才能很好支持自定义 OLAP 查询,由于维度长短不齐,这是一个看上去不规整立方体(cube),可以通过时间、维度、取值切蛋糕似得拿到 rowid 和 imei 的 bitmap 索引。这样就能很快找到维度条件关联的 rowid 计算 count 类指标,并拿到对应的 imei 的 bitmap 计算用户去重类指标。


Cube[t][d][v] = bitmap(rowid) ,bitmap(imei)


t:时间 (Z 轴) ,d:维度 (Y 轴) ,v:取值 (X 轴)


横切:查找 t2 时间数据,cube[t2][ ][ ]


竖切:查找 d2 维度数据, cube[ ][d2][ ]


切块:查找 t0-t1 时间,d0=v0 and d0=v1 的数据,cube[<2][d0][<2] (红框内)



2、锋刃 + Druid 的 OLAP 架构方案


如果我们不是直接自研实现,而是把锋刃和 Druid 通过如下架构方案集成,也是可以间接满足上面的 cube 的索引模型,虽然看上去有一点小别扭。


(1)锋刃继续承担消息的接入、实时清洗、和用户去重,这里把用户去重分成上面归纳的两种类型,一类是实时出的关键指标,基于内存结构;一类是可适当延迟出的所有维度指标,基于持久化存储,把这两部分的用户去重结果都导入到 Druid。


(2)Druid 承担所有维度的自定义查询,由于锋刃完成了用户去重的功能,druid 除了可以快速根据自定义维度过滤,并完成 count 类指标统计外,还可以同时查到用户去重的结果,结果记录是按照 group 展开的。



我们注意到上面的方案还有一点缺陷,如果查出一个时间范围内的多条用户结果,不能通过 druid 直接合并显示,这时需要返回锋刃系统找到对应的用户 bitmap 再做去重后返回结果。


(3)我们把用户的自定义查询过程封装成一个统一的输入输出如下,这样看上去就是一个基本实现 OLAP 功能的完整方案了。


总结

本文从集群压力到大数据平台整体架构,再到实时优化的切入,一步步阐述了锋刃大数据系统产生的来龙去脉,重点介绍了流式处理结合 bitmap 技术架构方案的主要原理,相关业务场景实施上线,以及后续的 OLAP 目标规划。关于锋刃大数据系统更多的内容,请参考锋刃团队后续的设计文档、使用指南、以及开源计划。

作者介绍

彭渊,现任腾讯 T4 专家,历任阿里资深专家,华为中间件首席架构师,淘宝高级专家等。在中国 IT 互联网技术领域从业多年,曾撰写多款开源软件,代表作有 Fourinone(四不像)分布式核心技术框架、CoolHash 并行数据库引擎等,曾出版书籍《大规模分布式系统架构与设计实战》,拥有多项软件著作权和专利。


2018-11-20 11:139670

评论 4 条评论

发布
用户头像
同问 附件呢?
2019-06-25 16:32
回复
用户头像
附件在哪里?
2019-03-13 14:00
回复
用户头像
为了方便读者理解上面的思想,作者抽取出了两个简化的 java 实现类供参考,CoolBitSet.java 实现了 bitmap 的所有操作,CoolBitMap.java 是集成了数组和 bitmap 存储的高级结构,可在附件下载。

没看到有附件啊~
2019-02-27 10:54
回复
用户头像
前面都是大数据普遍会遇到的问题,到了Bitmap这里,真是绝妙的技术解决方案,厉害厉害,是得有多年的实践经验总,才能设计出来的解决方案
2018-11-21 13:22
回复
没有更多了
发现更多内容

JAVA新特性的入场券-函数式接口

蜜糖的代码注释

Java 后端 Java高级特性

浅谈 Java 集合框架

宇宙之一粟

java集合总结 1月月更

WebRTC 流媒体常见开源方案综述 | 社区征文

liuzhen007

音视频 新春征文 2月月更

树概念总结

en

数据结构

微服务架构实践原则

俞凡

架构 微服务

Kubectl插件开发及开源发布分享| 社区征文

雪雷

golang 云原生 cobra kubectl plugin 新春征文

2021,平(jia)凡(ban)的一年

xiezhr

年终总结 2021 2021年终总结

特征工程:归一化与标准化

强劲九

Python 人工智能 神经网络 机器学习 scikit-learn

ReactNative进阶(四十三):Mac 通过 .bash_profile 文件配置环境变量

No Silver Bullet

Mac 2月月更 .bash_profile

从 TDD 到测试策略

Teobler

前端 TDD 单元测试 测试策略 测试金字塔

在线格式时间计算时间差

入门小站

工具

Java9特性-响应式流(Reactive Stream)

蜜糖的代码注释

Java 响应式 响应式编程 2月月更

我所理解的云原生(二)

劼哥stone

云原生

我的2021

劼哥stone

年终总结

【优化技术专题】「系统性能调优实战」终极关注应用系统性能调优及原理剖析(下册)

洛神灬殇

性能调优 Java 分布式 优化逻辑 技术职场 1月日更

Linux之killall命令

入门小站

Linux

Spotify系统架构

俞凡

架构 大厂实践 2月月更 spotify

TTF、OTF、WOFF 和 WOFF2 的相关概念

编程三昧

CSS css3 1月月更

从IaC到IaD

俞凡

云计算 基础设施即代码

Promise 基本方法的简单实现

编程三昧

JavaScript Promise 2月月更

ReactNative进阶(四十四):Mobile App 适配性优化

No Silver Bullet

React Native 适配 1月月更

简单入门计算机网络

宇宙之一粟

计算机网络 2月月更

聊聊API安全的重要性及治理思路

陈俊

安全 API 应用架构

行业研究流程及资源总结

轻口味

android AI 1月月更

ReactNative进阶(四十六):移动端实现字体自适应

No Silver Bullet

自适应 React Native 2月月更

Kubernetes初学者指南

俞凡

架构 Kubernetes 云原生 2月月更

第六周作业

cqyanbo

2021年度总结-拥抱变化

wood

300天创作

Windows 和 Linux 上安装 TTF 字体的方法

编程三昧

HTML5, CSS3 1月月更

Mybatis技术专题之MybatisPlus自带强大功能之多租户插件实现原理和实战分析

洛神灬殇

多租户 MyBatisPlus 2月日更 多租户技术

Java NIO为何导致堆外内存OOM了?

JavaEdge

2月月更

每日生产万亿消息数据入库,腾讯如何突破大数据分析架构瓶颈_大数据_彭渊_InfoQ精选文章