Kafka在美团数据平台的现状
Kafka出色的I/O优化以及多处异步化设计,相比其他消息队列系统具有更高的吞吐,同时能够保证不错的延迟,十分适合应用在整个大数据生态中。
目前在美团数据平台中,Kafka承担着数据缓冲和分发的角色。如下图所示,业务日志、接入层Nginx日志或线上DB数据通过数据采集层发送到Kafka,后续数据被用户的实时作业消费、计算,或经过数仓的ODS层用作数仓生产,还有一部分则会进入公司统一日志中心,帮助工程师排查线上问题。
目前美团线上Kafka规模:
-
集群规模:节点数达6000+,集群数100+。
-
集群承载:Topic数6万+,Partition数41万+。
-
处理的消息规模:目前每天处理消息总量达8万亿,峰值流量为1.8亿条/秒
-
提供的服务规模:目前下游实时计算平台运行了3万+作业,而这其中绝大多数的数据源均来自Kafka。
Kafka线上痛点分析&核心目标
当前Kafka支撑的实时作业数量众多,单机承载的Topic和Partition数量很大。这种场景下很容易出现的问题是:同一台机器上不同Partition间竞争PageCache资源,相互影响,导致整个Broker的处理延迟上升、吞吐下降。
接下来,我们将结合Kafka读写请求的处理流程以及线上统计的数据来分析一下Kafka在线上的痛点。
原理分析
Kafka处理读写流程的示意图
对于Produce请求:Server端的I/O线程统一将请求中的数据写入到操作系统的PageCache后立即返回,当消息条数到达一定阈值后,Kafka应用本身或操作系统内核会触发强制刷盘操作(如左侧流程图所示)。
对于Consume请求:主要利用了操作系统的ZeroCopy机制,当Kafka Broker接收到读数据请求时,会向操作系统发送sendfile系统调用,操作系统接收后,首先试图从PageCache中获取数据(如中间流程图所示);如果数据不存在,会触发缺页异常中断将数据从磁盘读入到临时缓冲区中(如右侧流程图所示),随后通过DMA操作直接将数据拷贝到网卡缓冲区中等待后续的TCP传输。
综上所述,Kafka对于单一读写请求均拥有很好的吞吐和延迟。处理写请求时,数据写入PageCache后立即返回,数据通过异步方式批量刷入磁盘,既保证了多数写请求都能有较低的延迟,同时批量顺序刷盘对磁盘更加友好。处理读请求时,实时消费的作业可以直接从PageCache读取到数据,请求延迟较小,同时ZeroCopy机制能够减少数据传输过程中用户态与内核态的切换,大幅提升了数据传输的效率。
但当同一个Broker上同时存在多个Consumer时,就可能会由于多个Consumer竞争PageCache资源导致它们同时产生延迟。下面我们以两个Consumer为例详细说明:
如上图所示,Producer将数据发送到Broker,PageCache会缓存这部分数据。当所有Consumer的消费能力充足时,所有的数据都会从PageCache读取,全部Consumer实例的延迟都较低。此时如果其中一个Consumer出现消费延迟(图中的Consumer Process2),根据读请求处理流程可知,此时会触发磁盘读取,在从磁盘读取数据的同时会预读部分数据到PageCache中。当PageCache空间不足时,会按照LRU策略开始淘汰数据,此时延迟消费的Consumer读取到的数据会替换PageCache中实时的缓存数据。后续当实时消费请求到达时,由于PageCache中的数据已被替换掉,会产生预期外的磁盘读取。这样会导致两个后果:
-
消费能力充足的Consumer消费时会失去PageCache的性能红利。
-
多个Consumer相互影响,预期外的磁盘读增多,HDD负载升高。
我们针对HDD的性能和读写并发的影响做了梯度测试,如下图所示: