databus indigestible

时间:2023-05-03 04:00/span> 作者:tiger 分类: 经验 浏览:5410 评论:0

埋点数据流治理实践

介绍完埋点数据流建设的实践,接下来给大家分享的是埋点数据流治理方面的一些实践。埋点数据流治理包含多个治理领域,比如稳定性、成本、埋点质量等,每个治理领域下面又有很多具体的治理项目。

比如在稳定性治理中我们通过优化减少了由于单机问题、MQ性能问题和混布问题等导致的各种稳定性问题;

成本治理方面,我们通过组件选型、性能优化、埋点治理等方式取得了显著降本增效的成果;

埋点质量治理方面,我们对脏数据问题、埋点字段类型错误问题和埋点数据的丢失重复问题进行了监控和治理。

这次我们主要选取了其中部分治理项目和大家分享。

单机问题优化

  • Flink BacklogRescale

Yarn单机问题导致Flink 任务Failover、反压、消费能力下降是比较常见的case。

单机问题的类型有很多:队列负载不均、单机load高或者其他进程导致CPU负载高,以及一些硬件故障都可能导致Yarn单机问题。针对Yarn单机问题,我们从Flink和Yarn两个层面分别进行了优化,最终使单机load高导致的数据延迟减少了80%以上。

首先是Flink层面的优化,在埋点数据流ETL场景中,为了减少不必要的网络传输,我们的Partitioner主要采用的是Rescale Partitioner,而Rescale Partitioner会使用Round-Robin的方式发送数据到下游Channel中。由于单机问题可能导致下游个别Task反压或者处理延迟从而引起反压,而实际上在这个场景里面,数据从上游task发送到任何一个下游的Task都是可以的,合理的策略应该是根据下游的Task的处理能力去发送数据,而不是用Round-Robin方式。

另一方面我们注意到Flink Credit-Based flow control反压机制中,可以用backlog size去判断下游Task的处理负载,我们也就可以将Round Robin的发送方式修改为根据Channel的Backlog size信息,去选择负载更低的下游Channel进行发送。这个Feature上线后,队列的负载变得更加均衡,CPU的使用率也提升了10%。

  • Yarn优化

Yarn层面的优化,第一个是队列资源层面,我们使用独立的Label队列可以避免高峰期被其他低优任务影响。

第二个是对于Yarn节点上的DataNode把带宽打满或者CPU使用比较高影响节点上埋点数据流Flink任务稳定性的情况,通过给DataNode进行网络限速,CPU绑核等操作,避免了DataNode对Flink进程的影响。

第三个是Yarn反调度的策略,目前字节跳动Flink使用的Yarn Gang Scheduler会按条件约束选择性地分配Yarn资源,在任务启动时均衡的放置Container,但是由于时间的推移,流量的变化等各种因素,队列还是会出现负载不均衡的情况,所以反调度策略就是为了解决这种负载不均衡而生的二次调度机制。

反调度策略中,Yarn会定期检查不满足原有约束的Container,并在这些Container所在节点上筛选出需要重新调度的Container返还给Flink Job Manager,然后Flink会重新调度这些Container,重新调度会按照原有的约束条件尝试申请等量的可用资源,申请成功后再进行迁移。

另外我们会针对一些频繁出问题的节点把它们加入调度的黑名单,在调度的时候避免将container调度到这些节点。

MQ优化

  • Databus应用

在流量迅速增长的阶段,埋点数据流Flink任务一开始是通过Kafka Connecter直接写入Kafka。但由于任务处理的流量非常大,Flink任务中Sink并发比较多,导致批量发送的效率不高,Kafka集群写入的请求量非常大。并且由于每个Sink一个或多个Client,Client与Kafka之间建立的连接数也非常多。而Kafka由于Controller的性能瓶颈无法继续扩容,所以为了缓解Kafka集群的压力,埋点数据流的Flink任务引入了Databus组件。Databus是一种以Agent方式部署在各个节点上的MQ写入组件。Databus Agent可以配置多个Channel,每个Channel对应一个Kafka的Topic。

Flink Job每个Task Manager里面的Sink会通过Unix Domain Socket的方式将数据发送到节点上Databus Agent的Channel里面,再由Databus将数据批量地发送到对应的Kafka Topic。由于一个节点上会有多个Task Manager,每个Task Manager都会先把数据发送到节点上的Databus Agent,Databus Agent中的每个Channel实际上聚合了节点上所有Task Manager写往同一个Topic数据,因此批量发送的效率非常高,极大地降低了Kafka集群的写入请求量,并且与Kafka集群之间建立的连接数也更少,通过Agent也能方便地设置数据压缩算法,由于批量发送的原因压缩效率比较高。在我们开启了Zstd压缩后,Kafka集群的写入带宽降低了37%,极大地缓解了Kafka集群的压力。

  • Kafka迁移BMQ

在埋点数据流这种大流量场景下使用Kafka,会经常遇到Broker或者磁盘负载不均、磁盘坏掉等情况导致的稳定性问题,以及Kafka扩容、Broker替换等运维操作也会影响集群任务正常的读写性能,除此之外Kafka还有controller性能瓶颈、多机房容灾部署成本高等缺点。

为了优化这些问题,BMQ这款字节跳动自研的存储计算分离的MQ应运而生。BMQ的数据存储使用了HDFS分布式存储,每个Partition的数据切分为多个segment,每个segment对应一个HDFS文件,Proxy和Broker都是无状态的,因此可以支持快速的扩缩容,并且由于没有数据拷贝所以扩缩容操作也不会影响读写性能。

受益于HDFS已经建设得比较完善的多机房容灾能力,BMQ多机房容灾部署就变的非常简单,数据同时写入所有容灾机房后再返回成功即可保障多机房容灾。数据消费是在每个机房读取本地的HDFS进行消费,减少了跨机房带宽。除此之外,由于基于多机房HDFS存储比Kafka集群多机房部署所需的副本更少,所以最终实现了单GB流量成本对比Kafka下降了50%的资源收益。

成本治理-埋点治理

在埋点治理方面,通过对流量平台的建设,提供了从埋点设计、埋点注册、埋点验证、埋点上报、埋点采样、流式ETL处理,再到埋点下线的埋点全生命周期的管理能力。

  • 埋点管控

目前字节跳动所有的产品都开启了埋点管控。所有的埋点都需要在我们的流量平台上注册埋点元数据之后才能上报。而我们的埋点数据流ETL也只会处理已经注册的埋点,这是从埋点接入流程上进行的管控。

在埋点上报环节,通过在流量平台配置埋点的采样率对指定的埋点进行采样上报,在一些不需要统计全量埋点的场景能显著地降低埋点的上报量。

对于已经上报的埋点,通过埋点血缘统计出已经没有在使用的埋点,自动通知埋点负责人在流量平台进行自助下线。埋点下线流程完成后会通过服务端动态下发配置到埋点SDK以及埋点数据流ETL任务中,确保未注册的埋点在上报或者ETL环节被丢弃掉。还支持通过埋点黑名单的方式对一些异常的埋点进行动态的封禁。

  • 埋点分级

埋点分级主要是针对离线存储成本进行优化,首先在流量平台上对埋点进行分级,埋点数据流ETL任务会将分级信息写入到埋点数据中。埋点数据在从MQ Dump到HDFS这个阶段根据这些分级的信息将埋点数据写入不同的HDFS分区路径下。然后通过不同的Spark任务消费不同分级分区的HDFS数据写入Hive Table。不同等级的分区可以优先保障高优埋点的产出,另外不同分区也可以配置不同的TTL,通过缩减低优数据的TTL节省了大量的存储资源。

未来规划

目前Flink能做到计算层面的流批一体,但计算和存储的流批一体还在探索阶段,接下来我们也会继续关注社区的进展。另外我们会尝试探索一些云原生的实时数据处理框架,尝试解决资源动态rescale的问题,以此来提升资源利用率。最后是在一些高优链路上,我们希望保障更高的SLA,比如端到端的exactly-once语义。

相关技术实践已经通过火山引擎数据中台产品对外输出,大家感兴趣的话也可以登陆火山引擎的官网进行了解。

作者:石伟 字节跳动数据平台开发套件团队

相关文章

文章评论