一、背景
随着公司游戏业务的高速发展,越来越多的分析需求涌现,例如:各类游戏用户行为分析、商业智能分析、数仓报表等。这些场景的数据体量都较大,对数据分析平台提出了很高的要求。为了解决实时分析的时效性,同时又能保证数据快速写入和查询,需要一个合适的数据查询引擎来补充我们原有的架构体系。
经过大量调研,ApacheDoris比较契合网易互娱游戏数据中心的整体要求,ApacheDoris具备以下 特性:
MPP架构+高效列式存储引擎
高性能、高可用、高弹性
标准ANSISQL支持
支持多表Join
支持MySQL协议
支持预聚合
支持物化视图
支持预聚合结果自动更新
支持数据高效的批量导入、实时导入
支持数据的实时更新
支持高并发查询
周边生态完善
网易互娱于年4月引入了ApacheDoris产品,目前已经发展为多个集群,服务数十个业务,如游戏舆情分析,实时日活看板、用户事件分析、留存分析、漏斗分析、分布分析等。当前OLAP平台与数仓体系融合的架构如下图所示:
图1.OLAP平台与数仓体系融合架构二、ApacheDoris简介
ApacheDoris是百度开源的MPP分析型数据库产品,不仅能够在亚秒级响应时间即可获得查询结果,有效的支持实时数据分析,而且支持PB级别的超大数据集。相较于其他业界比较火的OLAP数据库系统,Doris的分布式架构非常简洁,只有FE、BE两个服务,整体运行不依赖任何第三方系统,支持弹性伸缩,对于业务线部署运维到使用都非常友好。目前国内社区火热,也有腾讯、字节跳动、美团、小米等大厂在使用。
图2.ApacheDoris架构2.1FEFE的主要作用将SQL语句转换成BE能够认识的Fragment,如果把BE集群当成一个分布式的线程池的话,那么Fragment就是线程池中的Task。从SQL文本到分布式物理执行计划,FE的主要工作需要经过以下几个步骤:
SQLParse:将SQL文本转换成一个AST(抽象语法树)
SQLAnalyze:基于AST进行语法和语义分析
SQLLogicalPlan:将AST转换成逻辑计划
SQLOptimize:基于关系代数,统计信息,Cost模型对逻辑计划进行重写,转换,基于Cost选出成本 的物理执行计划
生成PlanFragment:将Optimizer选择的物理执行计划转换为BE可以直接执行的PlanFragment
执行计划的调度
图3.FE执行SQL流程2.2BEBE是Doris的后端节点,负责数据存储以及SQL计算执行等工作。
BE节点都是完全对等的,FE按照一定策略将数据分配到对应的BE节点。在数据导入时,数据会直接写入到BE节点,不会通过FE中转,BE负责将导入数据写成对应的格式以及生成相关索引。在执行SQL计算时,一条SQL语句首先会按照具体的语义规划成逻辑执行单元,然后再按照数据的分布情况拆分成具体的物理执行单元。物理执行单元会在数据存储的节点上进行执行,这样可以避免数据的传输与拷贝,从而能够得到 的查询性能。
图4.BE执行SQL流程三、集群治理3.1Compaction调优-Tablet治理在网易互娱引入ApacheDoris初期,业务用户在测试过程中发现建表时指定bucket数越大,查询速度越快,导致了用户在新建表和分区时统一将bucket数指定为64。随着导入的数据越来越多,问题也开始暴露了出来:业务陆续反馈alter分区失败、修改字段长度失败等问题。经过SA排查发现这些失败都是超时导致,同时发现业务操作的表数据量仅2G,replica数却达到了:
图5.业务表数据量及replica数更进一步地,为了将问题彻底暴露出来,对该集群进行全量统计发现60T的数据量达到了接近万的tablet数,tablet数过多会导致以下几个问题:
用户建分区,建表,修改字段等元数据操作耗时长,甚至会超时失败;
元数据都放在FE内存中,GC压力较大,同时FE在进行Checkpoint操作时由于元数据占用内存翻倍,极易出现OOM的风险;
bucket数是查询吞吐和查询并发的一种权衡,为了集群的健康发展,旧数据必须进行tablet治理,新的建表规范需建立起来。
3.1.1治理目标tablet数量=分区数*副本数*bucket数从上面的计算公式可知,在用户的场景下,前两者都是固定不变的,决定tablet数大小的只有bucket数。
鉴于该集群目前数据量大小为60T左右,结合对bucket的更进一步理解以及当前集群实际情况,治理的目标和长期控制的目标定为:
1.tablet数:w-w
2.tablet增长量:/TB
3.1.2实施计划(1)对于现存的表
扫描集群内所有的表,以分区粒度输出一份完整的数据统计给业务方,并根据每张表的实际情况附上修改建议;
制定治理计划按照由高收益到低收益,优先处理最不合理的库,将元数据管理压力降下来,再逐步按照计划治理所有的库。
因为Doris目前不支持按分区级别展示整个库下的数据情况,因此单独开发一个程序进行扫描,伪代码如下所示:
con=DriverManager.getConnection()fordbindb_list:con.execute("use%s".format(db)))fortableintable_list:con.execute("showcreatetable%s".format(table))#获取 个分区的bukcet数result.append(regrex_extract_bucket(con.next()))con.execute("showpartitionsfrom%s".format(table))result.append(regrex_extract_bucket(con.next()))#获取除 个分区的bukcet数write_result_to_excel(result)
截取部分写入Excel的数据,统计格式如下:
图6.Doris集群分区粒度数据统计及治理期望结合Excel 的透视表功能,即可轻松获取表粒度、以及库粒度下的治理建议统计表,最终治理目标也是依据计算出来的总期望分区数得到。以库粒度做统计截取部分数据如下所示:
图7.集群库粒度数据统计及治理期望根据统计表得到的信息,优先选择高收益率的库进行治理(上图中已标绿),对表的治理方式有以下两种方式:
种方式:数据重插
#鉴于Doris对所有已存在分区的bucket数无法修改的情况,使用新建表重插的方式进行,步骤为:1.createtablexxx_bakforpartitioninpartition_range:if(partition.data!=null)2.altertablexxx_bakaddpartitionifnotexistsdatebucket[动态值];//动态值根据每一个分区实际的数据量计算传入3.insertintoxxx_bakselect*fromxxxwheredt=date4.检查新的xxx数据量,分区数是否正确;//重点!!5.ALTERTABLExxxRENAMExxx_old;6.ALTERTABLExxx_bakRENAMExxx;7.dropxxx_old。-----方案说明:根据优先顺序对一张待治理的表进行步骤1和步骤2,第3步使用串行的方式提交执行(减少资源占用和出错的可能性)。执行完后根据数据验证方案对数据进行验证,确保无误后进行5,6操作。特别说明:因为迁移过程中仍然会有数据写入旧表,因此迁移过程中有两个内容要确保:1、在重插 的分区过程中,业务控制确保该时间段内没有数据流入;2、一张表的1-6步骤在下一次写入数据前完成。3、如未完成则单独标记,在当天结束写入数据和下次写入数据前完成该分区的重插。根据业务反馈大部分load分区操作都能在1分钟完成,所以重插的时间窗口是很大的。
使用该种方式对三种类型的表进行测试,结果如下:
小表测试21.5Mtablets
中表测试19Gtablets
大表测试Gtablets
第二种方式:数据重Load
#对于表数据在Hive数据还存在的,该方式更为简单1.droppartition2.createpartition3.loaddatafromHive
(2)对于未来新增表
对于业务方,业务在导入数据时增加判断逻辑,根据Hive表数据情况指定bucket数,建分区规范如下:
0-10M的数据量:1
10-50M的数据量:2
50M-2G的数据量:4
2-5G的数据量:8
5-25G的数据量:16
25-50G的数据量:32
超过50G的数据量:64
对于服务方,新增以下措施:
监控页面新增tablet_per_TB_data指标,及时检测到异常建表建分区的情况。
定期(如每月)统计哪些表还存在tablet优化的空间,提供给业务,并敦促改进。
3.1.3治理收益经过一段时间的治理,tablet数显著下降:由接近万下降到多万,业务反馈的元数据操作相关问题明显减少:
图8.tablet监控FE的堆内存占用明显下降,执行Checkpoint时,元数据会在内存中复制一份,表现在监控图上是一段尖峰,治理后尖峰变得更缓和,大大提升了FE的稳定性:
图9.FEJVMHeapStat3.1.4治理说明由于Hive中数据存储格式与Doris数据存储格式不同,因此在数据量判定方面存在差别,会导致SA在扫描分区tablet数时得到部分治理错误的结论,总体来说实际值会比预期值高,以某库为例:
图10.某库分区治理后验证结果3.2Compaction调优-StreamLoad治理3.2.1问题描述业务使用的某个Doris集群经常出现BE异常退出的情况,影响实时数据导入到Doris集群,查看监控显示CompactionCumulativeScore值波动十分异常:
图11.CompactionCumulativeScore监控Doris的数据写入模型使用了LSM-Tree类似的数据结构。数据都是以追加(Append)的方式写入磁盘的。这种数据结构可以将随机写变为顺序写。这是一种面向写优化的数据结构,他能增强系统的写入吞吐,但是在读逻辑中,需要通过Merge-on-Read的方式,在读取时合并多次写入的数据,从而处理写入时的数据变更。
Merge-on-Read会影响读取的效率,为了降低读取时需要合并的数据量,基于LSM-Tree的系统都会引入后台数据合并的逻辑,以一定策略定期的对数据进行合并。Doris中这种机制被称为Compaction。
该值可以反映当前版本堆积的情况,这个值在以内算正常,如果持续逼近,说明集群可能存在风险,而从图11中可以看到,该集群的CompactionScore周期性的逼近。
3.2.2Compaction参数调节通过监控图找到一个版本数量 的BE节点。然后执行以下命令分析日志:
grep"succeedtodocumulative