背景

为了提升小米成长分析平台的查询性能,降低平台的运维成本,小米集团于2019年9月首次引入Apache Doris。两年多来,Apache Doris已经在小米集团广泛使用。目前已服务成长分析、集团数据看板、明星金融、小米有品、用户画像、广告、A/B实验平台、新零售等数十项业务,如图1所示。在小米集团,质量是生命线。随着业务的不断增长,如何保证在线Doris集群的服务质量是集群运维人员面临的一大挑战。本文将从运维角度分享Apache Doris在小米集团的应用实践。
图Apache Doris在小米的业务分布集群部署和升级基于Apache Doris社区发布的稳定版本,小米还维护了内部的Doris分支,用于内部次要版本的迭代。由于编译Docker第三方库的硬件环境与社区的差异,基于社区Docker编译的Doris二进制包在小米在线环境下运行时会出现问题。所以小米内部也维护自己的Docker镜像,用于内部多丽丝分支的编译发布。内部分发时,源代码会被编译打包到Docker容器中,二进制包会通过弥诺斯上传到Tank服务器。小米内部的多丽丝分配流程如图2所示。
图2-小米内部多丽丝分销流程弥诺斯是小米开发的基于命令行的大数据部署和流程管理系统,支持多丽丝、HDFS、Hbase、Zookeeper等服务的部署和管理。在小米内部,可以通过弥诺斯完成包上传、集群部署、集群离线、集群升级、进程重启、配置更改等操作。弥诺斯对服务的管理依赖于配置文件deployment-config,其中配置了服务版本信息、集群节点信息和集群配置参数等信息。部署集群时,弥诺斯会根据deployment-config中配置的服务版本信息从Tank Server中拉取相应的二进制包,并根据deployment-config中配置的节点信息和集群参数部署集群。在群集部署之后,如果进程被丢弃,弥诺斯将自动恢复进程并恢复服务。轻舟是小米自主研发的分布式服务生命周期管理平台,从需求评估开始到资源下线结束,贯穿了分布式大数据系统的生命周期互联管理。主要由发布中心、检验中心、运营仓库、环境管理、故障管理、产能管理等组成。如图3所示,这些模块在逻辑上是互连的,数据是可互操作的。轻舟发布中心提供可整理、低代码、可视化的服务发布和流程管理能力。canoe发布中心底层依托弥诺斯,可以实现基于canoe的Doris服务的平台管理,包括集群部署、集群离线、集群升级、流程重启、配置变更等。如果Doris的FE或BE进程意外断开,canoe会自动拉起进程,恢复服务。
图3-canoe管理平台商业惯例Apache Doris在小米的典型商业行为如下:
01用户访问数据工场是小米为数据开发者和数据分析师开发的一站式数据开发平台。底层支持Doris、Hive、Kudu、Iceberg、ES、Talso、TiDB、MySQL等数据源,以及Flink、Spark、Presto等计算能力。
在小米内部,用户需要通过数据工场访问多丽丝服务。用户需要在数据工场注册,完成数据库建立审批。多丽丝运维校友会将根据用户在数据工作坊中提交的业务场景和数据使用预期进行接入审批和指导。用户可以在获得访问许可后使用Doris服务,并在数据车间中进行可视化建表和数据导入操作。
02 数据导入在小米的业务中,将数据导入多丽丝最常用的两种方式是流加载和代理加载。用户数据会分为实时数据和离线数据,用户的实时和离线数据一般会先写入Talos。来自Talos的离线数据将被汇集到HDFS,然后通过数据工作室导入到Doris。用户可以直接在数据工场提交Broker Load任务,将大量数据从HDFS导入多丽丝,或者在数据工场执行SparkSQL,从Hive查询数据。并且SparkSQL找到的数据通过Spark-Doris-Connector导入到Doris中,Spark-Doris-Connector底层封装流负载。Talos的实时数据一般会以两种方式导入Doris。一种方式是通过Flink对数据进行ETL,然后每隔一段时间通过Flink-Doris-Connector将一小批数据导入Doris。流负载封装在Flink-Doris-Connector的底部;另一种导入实时数据的方法是通过Spark Streaming封装的Stream Load,每隔一段时间向Doris导入一小批数据。
03 数据查询小米的多丽丝用户一般通过鲸算平台对多丽丝进行分析查询并展示结果。鲸数是小米开发的通用BI分析工具。用户可以通过鲸算平台查询和可视化多丽丝,实现用户行为分析和用户画像分析。
Doris的数据导入和数据查询模式如图4所示。
图Doris的数据导入和数据查询模式
04 Compaction 调优对于Doris来说,每次数据导入都会在存储层的相关数据切片下生成一个数据版本,压缩机制会异步合并导入生成的较小数据版本。小米有很多高频、高并发、接近实时的导入业务场景,短时间内会产生大量小版本。如果压缩不能及时合并数据版本,就会导致版本的积累。一方面,小版本太多会增加元数据的压力;另一方面,太多的版本会影响查询性能。在小米的使用场景中,很多表采用了唯一和聚合的数据模型,查询性能很大程度上依赖于数据的版本是否通过压缩及时合并。在我们的业务场景中,由于版本合并不及时,查询性能降低了几十倍,从而影响了在线服务。但是,压缩任务本身会消耗机器的CPU、内存和磁盘IO资源。过多的压缩会占用过多的机器资源,也会影响查询性能,还可能造成OOM。

要解决这个压实的问题,一方面我们从业务端入手,通过以下几个方面引导用户:
为表设置合理的分区和桶,避免产生过多的数据碎片。
规范用户的数据导入操作,尽可能减少数据导入的频率,增加单次导入的数据量,减少压实的压力。
避免过度使用删除操作。删除操作会在存储层的相关数据切片下生成删除版本,累积压缩任务遇到删除版本会被截断。此子任务只能合并累积点之后和删除版本之前的数据版本。累积点移动到删除版本后,删除版本交给后续的basecompression任务处理。如果删除操作用的太多,平板下会产生太多的删除版本,导致合并版本的累积压缩任务进展缓慢。使用删除操作并没有真正从磁盘上删除数据,而是在删除版本中记录了删除条件,在数据查询时被删除的数据会被Merge-On-Read过滤掉。只有在删除版本被基本压缩任务合并后,删除操作要删除的数据才能作为过期数据与陈旧行集一起从磁盘中清除。如果需要删除整个分区的数据,可以使用截断分区操作代替删除操作。
另一方面,我们从运营和维护方面优化了压缩:
根据不同的业务场景,为不同的集群配置不同的压缩参数。
适当降低基础压缩任务的优先级,提高累积压缩任务的优先级,因为基础压缩任务执行时间长,存在严重的写放大问题,而累积压缩任务执行速度更快,可以快速合并大量小版本。
版本积压报警,动态调整压缩参数。当压缩生成器生成压缩任务时,它将更新相应的度量,该度量记录BE节点上最大压缩分数的值。可以通过Grafana查看这个指标的走势,判断是否有版本积压。此外,我们还增加了版本积压警报。为了方便压缩参数的调整,我们从代码层面进行了优化,支持压缩策略和压缩线程数在运行时的动态调整,避免了调整压缩参数时需要重启进程。
支持手动触发指定表和分区下数据切片的压缩任务,提高指定表和分区下数据切片的压缩优先级。
监控和报警管理01监控系统Prometheus将定期从FE和BE中提取Doris的度量指标,并在Grafana监控面板中显示。基于canoe计数仓的服务元数据会自动注册在Zookeeper中,Prometheus会定期从Zookeeper中拉取最新的集群元数据信息,并动态显示在Grafana监控面板中。此外,我们还在Grafana中增加了Doris的大型查询列表、实时写入数据量、数据导入交易等常见故障排除数据的统计和显示广告牌,可以进行联动报警,以便Doris运维学员在集群出现异常时,能够在最短的时间内定位集群故障的原因。02 Falcon 报警猎鹰是小米广泛使用的监控报警系统。因为Doris原生提供了相对完整的度量接口,可以方便的提供基于Prometheus和Grafana的监控功能,所以我们在Doris服务中只使用Falcon的报警功能。
根据多丽丝故障的不同级别,我们将告警定义为P0、P1和P2:
P2告警:单节点故障告警。当单个节点指标或流程状态异常时,一般会以P2级别发送报警,报警信息会以小米办公消息的形式发送给报警组成员。
P1报警:短时间内查询延迟增加或集群写异常等短时异常情况将作为P1报警,报警信息以小米办公消息的形式发送给报警组成员。P1警报要求Oncall工程师响应和反馈。
P0报警:集群中查询延迟延长或写入异常的情况将作为P0报警给出,报警信息以小米办公消息+电话报警的形式发送。P0警报要求Oncall工程师在1分钟内做出响应,并协调资源进行故障恢复和恢复准备。
上述报警类型和情况是作为简单的例子给出的。事实上,为了维护Doris系统的稳定性,我们会有各种形式和不同级别的报警和巡视检查。
03 Cloud-DorisCloud-Doris是小米为内部Doris服务开发的数据采集组件。其主要能力在于检测Doris服务的可用性,收集内部关注的聚类指标数据。
比如:Cloud-Doris定期模拟用户对Doris系统的读写来检测服务的可用性。如果集群出现可用性异常,会通过Falcon报警;收集用户的读写数据,然后生成用户账单;收集表格级数据、不健康副本、过大平板等信息,通过Falcon对异常信息进行报警。
小米内部多丽丝服务的监控报警系统架构如图5所示。
图Doris服务的监控和报警系统结构
04 轻舟巡检对于容量、用户增长、资源分配等慢性隐患。,我们使用canoe的大数据服务统一巡逻平台进行巡逻和报告。一般巡视检查包括两部分:服务专项巡视检查和基础指标巡视检查。其中,服务专用巡检是指每个大数据服务特有的、不能通用的指标。对于Doris来说,主要包括:配额、碎片副本数、单个表中的列数、表分区数等。基本指标检查主要是指服务之间可以通用的检查指标,包括:守护进程状态、进程状态、CPU/MEM/磁盘、服务器故障和过保护提示、资源利用率等。
通过增加巡视检查的方式,很好地覆盖了难以提前报警的慢性隐患,为重大节日提供了无故障支持。
故障恢复当在线集群出现故障时,首要原则应该是快速恢复服务。如果故障原因明确,将根据具体原因进行处理,恢复服务。如果失败的原因不清楚,您应该在离开站点后尽快尝试重新启动该过程以恢复服务。
01 接入故障处理多丽丝采用小米LVS作为接入层,类似于开源或公有云的LB服务,提供4层或7层流量负载调度能力。用户通过VIP连接到Doris集群。Doris绑定合理的探针端口后,一般来说,如果单个FE节点出现异常,会自动踢出,在用户不知情的情况下,服务可以恢复。同时会对异常节点进行报警。当然,对于短时间内无法处理的FE故障,我们会先将故障节点的权重调整为0,或者将异常节点从LVS中删除,以防止异常的进程激活带来不可预知的问题。
02 节点故障处理对于FE节点故障,如果不能快速定位故障原因,一般需要保留线程快照和内存快照后再重新启动进程。您可以通过以下命令保存FE的线程快照:
Jstack进程ID > >快照文件名。jstack
使用以下命令保存FE的内存快照:
Jmap -dump:live,format=b,file=快照文件名。堆进程ID
在版本升级或者一些意外场景的情况下,FE节点的镜像可能会有异常元数据,异常元数据可能会同步到其他FE,导致所有FE无法工作。一旦发现映像有问题,最快的恢复方案是使用恢复模式停止FE选举,并用备份映像替换有问题的映像。当然,一直备份映像并不容易。由于这种故障在集群升级中很常见,我们建议在集群升级的程序中增加简单的本地镜像备份逻辑,以确保在每次升级启动FE进程之前保留最新镜像数据的副本。
对于BE节点故障,如果进程崩溃,会生成核心文件,minos会自动拉进程;如果任务停滞,您需要保留线程快照,并通过以下命令重新启动进程:
Pstack进程ID > >快照文件名。pstack
结束语自2019年9月小米集团首次引入Apache Doris以来,Apache Doris已经在小米广泛使用了两年多。目前已服务小米数十个业务,数十个集群,数百个节点,形成了一套以Apache Doris为核心的数据生态。为了提高运维效率,小米还围绕多丽丝开发了一整套自动化管理和运维系统。服务越来越多,当然多丽丝也暴露了一些问题,比如过去的版本没有更好的资源隔离机制,服务之间会互相影响。此外,系统监测需要改进。随着社区的快速发展,越来越多的小伙伴参与到社区建设中,矢量化引擎的改造已经基本完成,查询优化器的改造也在紧锣密鼓的进行中,Apache Doris也逐渐走向成熟。

最后,祝Apache Doris社区发展越来越好!
-作者简介-
小米OLAP引擎研发工程师、Apache Doris委托人佐为,主要负责小米Apache Doris的研发和优化。孟子楠小米存储计算引擎SRE负责小米分布式存储引擎运维研发和大数据组件运营平台研发。


