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 在线上的痛点。
原理剖析
对于 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 的性能和读写并发的影响做了梯度测试,如下图所示:
能够看到,随着读并发的减少,HDD 的 IOPS 和带宽均会显著降落,这会进一步影响整个 Broker 的吞吐以及解决提早。
线上数据统计
目前 Kafka 集群 TP99 流量在 170MB/s,TP95 流量在 100MB/s,TP50 流量为 50-60MB/s;
单机的 PageCache 平均分配为 80GB,取 TP99 的流量作为参考,在此流量以及 PageCache 分配情况下,PageCache 最大可缓存数据时间跨度为 80*1024/170/60 = 8min,可见以后 Kafka 服务整体对提早生产作业的容忍性极低。该状况下,一旦局部作业生产提早,实时生产作业就可能会受到影响。
同时,咱们统计了线上实时作业的生产提早散布状况,提早范畴在 0 -8min(实时生产)的作业只占 80%,阐明目前存在线上存在 20% 的作业处于提早生产的状态。
痛点剖析总结
总结上述的原理剖析以及线上数据统计,目前线上 Kafka 存在如下问题:
- 实时生产与提早生产的作业在 PageCache 档次产生竞争,导致实时生产产生非预期磁盘读。
- 传统 HDD 随着读并发升高性能急剧下降。
- 线上存在 20% 的提早生产作业。
按目前的 PageCache 空间调配以及线上集群流量剖析,Kafka 无奈对实时生产作业提供稳固的服务质量保障,该痛点亟待解决。
预期指标
根据上述痛点剖析,咱们的预期指标为保障实时生产作业不会因为 PageCache 竞争而被提早生产作业影响,保障 Kafka 对实时生产作业提供稳固的服务质量保障。
解决方案
为什么抉择 SSD
根据上述起因剖析可知,解决目前痛点可从以下两个方向来思考:
- 打消实时生产与提早生产间的 PageCache 竞争,如:让提早生产作业读取的数据不回写 PageCache,或增大 PageCache 的调配量等。
- 在 HDD 与内存之间退出新的设施,该设施领有比 HDD 更好的读写带宽与 IOPS。
对于第一个方向,因为 PageCache 由操作系统治理,若批改其淘汰策略,那么实现难度较为简单,同时会毁坏内核自身对外的语义。另外,内存资源老本较高,无奈进行无限度的扩大,因而须要思考第二个方向。
SSD 目前倒退日益成熟,相较于 HDD,SSD 的 IOPS 与带宽领有数量级级别的晋升,很适宜在上述场景中当 PageCache 呈现竞争后承接局部读流量。咱们对 SSD 的性能也进行了测试,后果如下图所示:
从图中能够发现,随着读取并发的减少,SSD 的 IOPS 与带宽并不会显著升高。通过该论断可知,咱们能够应用 SSD 作为 PageCache 与 HDD 间的缓存层。
架构决策
在引入 SSD 作为缓存层后,下一步要解决的关键问题包含 PageCache、SSD、HDD 三者间的数据同步以及读写申请的数据路由等问题,同时咱们的新缓存架构须要充沛匹配 Kafka 引擎读写申请的特色。本大节将介绍新架构如何在选型与设计上解决上述提到的问题。
Kafka 引擎在读写行为上具备如下个性:
- 数据的生产频率随工夫变动,越长远的数据生产频率越低。
- 每个分区(Partition)只有 Leader 提供读写服务。
- 对于一个客户端而言,消费行为是线性的,数据并不会反复生产。
下文给出了两种备选计划,上面将对两种计划给出咱们的选取根据与架构决策。
备选计划一:基于操作系统内核层实现
目前开源的缓存技术有 FlashCache、BCache、DM-Cache、OpenCAS 等,其中 BCache 和 DM-Cache 曾经集成到 Linux 中,但对内核版本有要求,受限于内核版本,咱们仅能选用 FlashCache/OpenCAS。
如下图所示,FlashCache 以及 OpenCAS 二者的外围设计思路相似,两种架构的外围理论依据为“数据局部性”原理,将 SSD 与 HDD 依照雷同的粒度拆成固定的治理单元,之后将 SSD 上的空间映射到多块 HDD 层的设施上(逻辑映射 or 物理映射)。在拜访流程上,与 CPU 拜访高速缓存和主存的流程相似,首先尝试拜访 Cache 层,如果呈现 CacheMiss,则会拜访 HDD 层,同时依据数据局部性原理,这部分数据将回写到 Cache 层。如果 Cache 空间已满,会通过 LRU 策略替换局部数据。
FlashCache/OpenCAS 提供了四种缓存策略:WriteThrough、WriteBack、WriteAround、WriteOnly。因为第四种不做读缓存,这里咱们只看前三种。
写入:
- WriteThrough:数据写操作在写入 SSD 的同时会写入到后端存储。
- WriteBack:数据写操作仅写入 SSD 即返回,由缓存策略 flush 到后盾存储。
- WriteAround:数据写入操作间接写入后端存储,同时 SSD 对应的缓存会生效。
读取:
- WriteThrough/WriteBack/WriteAround:首先读取 SSD,命中不了的将再次读取后端存储,并数据会被刷入到 SSD 缓存中。
更多具体实现细节,极大可参见这二者的官网文档:
- FlashCache
- OpenCAS
备选计划二:Kafka 利用外部实现
上文提到的第一类备选计划中,外围的理论依据“数据局部性”原理与 Kafka 的读写个性并不能齐全吻合,“数据回刷”这一个性仍然会引入缓存空间净化问题。同时,上述架构基于 LRU 的淘汰策略也与 Kafka 读写个性存在矛盾,在多 Consumer 并发生产时,LRU 淘汰策略可能会误淘汰掉一些近实时数据,导致实时生产作业呈现性能抖动。
可见,备选计划一并不能齐全解决以后 Kafka 的痛点,须要从利用外部进行革新。整体设计思路如下,将数据依照工夫维度散布在不同的设施中,近实时局部的数据缓存在 SSD 中,这样当呈现 PageCache 竞争时,实时生产作业从 SSD 中读取数据,保障实时作业不会受到提早生产作业影响。下图展现了基于应用层实现的架构解决读申请的流程:
当生产申请达到 Kafka Broker 时,Kafka Broker 间接依据其保护的音讯偏移量(Offset)和设施的关系从对应的设施中获取数据并返回,并且在读申请中并不会将 HDD 中读取的数据回刷到 SSD,防止出现缓存净化。同时拜访门路明确,不会因为 Cache Miss 而产生的额定拜访开销。
下表对不同候选计划进行了更加具体的比照:
最终,联合与 Kafka 读写个性的匹配度,整体工作量等因素综合思考,咱们采纳 Kafka 应用层实现这一计划,因为该计划更贴近 Kafka 自身读写个性,能更加彻底地解决 Kafka 的痛点。
新架构设计
概述
依据上文对 Kafka 读写个性的剖析,咱们给出应用层基于 SSD 的缓存架构的设计指标:
- 数据按工夫维度散布在不同的设施上,近实时数据分布在 SSD 上,随工夫的推移淘汰到 HDD 上。
- Leader 分区中所有数据均写入 SSD 中。
- 从 HDD 中读取的数据不回刷到 SSD 中。
根据上述指标,咱们给出应用层基于 SSD 的 Kafka 缓存架构实现:
Kafka 中一个 Partition 由若干 LogSegment 形成,每个 LogSegment 蕴含两个索引文件以及日志音讯文件。一个 Partition 的若干 LogSegment 按 Offset(绝对工夫)维度有序排列。
依据上一大节的设计思路,咱们首先将不同的 LogSegment 标记为不同的状态,如图所示(图中上半局部)依照工夫维度分为 OnlyCache、Cached 以及 WithoutCache 三种常驻状态。而三种状态的转换以及新架构对读写操作的解决如图中下半局部所示,其中标记为 OnlyCached 状态的 LogSegment 只存储在 SSD 上,后盾线程会定期将 Inactive(没有写流量)的 LogSegment 同步到 SSD 上,实现同步的 LogSegment 被标记为 Cached 状态。最初,后盾线程将会定期检测 SSD 上的应用空间,当空间达到阈值时,后盾线程将会依照工夫维度将间隔当初最久的 LogSegment 从 SSD 中移除,这部分 LogSegment 会被标记为 WithoutCache 状态。
对于写申请而言,写入申请仍然首先将数据写入到 PageCache 中,满足阈值条件后将会刷入 SSD。对于读申请(当 PageCache 未获取到数据时),如果读取的 offset 对应的 LogSegment 的状态为 Cached 或 OnlyCache,则数据从 SSD 返回(图中 LC2-LC1 以及 RC1),如果状态为 WithoutCache,则从 HDD 返回(图中 LC1)。
对于 Follower 正本的数据同步,可依据 Topic 对提早以及稳定性的要求,通过配置决定写入到 SSD 还是 HDD。
要害优化点
上文介绍了基于 SSD 的 Kafka 应用层缓存架构的设计概要以及外围设计思路,包含读写流程、外部状态治理以及新增后盾线程性能等。本大节将介绍该计划的要害优化点,这些优化点均与服务的性能非亲非故。次要包含 LogSegment 同步以及 Append 刷盘策略优化,上面将别离进行介绍。
LogSegment 同步
LogSegment 同步是指将 SSD 上的数据同步到 HDD 上的过程,该机制在设计时次要有以下两个关键点:
- 同步的形式:同步形式决定了 HDD 上对 SSD 数据的可见时效性,从而会影响故障复原以及 LogSegment 清理的及时性。
- 同步限速:LogSegment 同步过程中通过限速机制来避免同步过程中对失常读写申请造成影响
同步形式
对于 LogSegment 的同步形式,咱们给出了三种备选计划,下表列举了三种计划的介绍以及各自的优缺点:
最终,咱们对一致性保护代价、实现复杂度等因素综合思考,抉择了后盾同步 Inactive 的 LogSegment 的形式。
同步限速
LogSegment 同步行为实质上是设施间的数据传输,会同时在两个设施上产生额定的读写流量,占用对应设施的读写带宽。同时,因为咱们抉择了同步 Inactive 局部的数据,须要进行整段的同步。如果在同步过程中不加以限度会对服务整体提早造成较大的影响,次要体现在上面两个方面:
- 从单盘性能角度,因为 SSD 的性能远高于 HDD,因而在数据传输时,HDD 写入带宽会被写满,此时其余的读写申请会呈现毛刺,如果此时有提早生产从 HDD 上读取数据或者 Follower 正在同步数据到 HDD 上,会造成服务抖动。
- 从单机部署的角度,单机会部署 2 块 SSD 与 10 块 HDD,因而在同步过程中,1 块 SSD 须要接受 5 块 HDD 的写入量,因而 SSD 同样会在同步过程中呈现性能毛刺,影响失常的申请响应提早。
基于上述两点,咱们须要在 LogSegment 同步过程中减少限速机制,总体的限速准则为在不影响失常读写申请提早的状况下尽可能疾速地进行同步。因为同步速度过慢会导致 SSD 数据无奈被及时清理而最终被写满。同时为了能够灵便调整,该配置也被设置为单 Broker 粒度的配置参数。
日志追加刷盘策略优化
除了同步问题,数据写入过程中的刷盘机制同样影响服务的读写提早。该机制的设计不仅会影响新架构的性能,对原生 Kafka 同样会产生影响。
下图展现了单次写入申请的解决流程:
在 Produce 申请解决流程中,首先依据以后 LogSegment 的地位与申请中的数据信息确定是否须要滚动日志段,随后将申请中的数据写入到 PageCache 中,更新 LEO 以及统计信息,最初依据统计信息确定是否须要触发刷盘操作,如果须要则通过 fileChannel.force
强制刷盘,否则申请间接返回。
在整个流程中,除日志滚动与刷盘操作外,其余操作均为内存操作,不会带来性能问题。日志滚动波及文件系统的操作,目前,Kafka 中提供了日志滚动的扰动参数,避免多个 Segment 同时触发滚动操作给文件系统带来压力。针对日志刷盘操作,目前 Kafka 给出的机制是以固定音讯条数触发强制刷盘(目前线上为 50000),该机制只能保障在入流量肯定时,音讯会以雷同的频率刷盘,但无奈限度每次刷入磁盘的数据量,对磁盘的负载无奈提供无效的限度。
如下图所示,为某磁盘在午顶峰时间段 write_bytes 的瞬时值,在午顶峰时间段,因为写入流量的回升,在刷盘过程中会产生大量的毛刺,而毛刺的值简直靠近磁盘最大的写入带宽,这会使读写申请提早产生抖动。
针对该问题,咱们批改了刷盘的机制,将本来的按条数限度批改为按理论刷盘的速率限度,对于单个 Segment,刷盘速率限度为 2MB/s。该值思考了线上理论的均匀音讯大小,如果设置过小,对于单条音讯较大的 Topic 会过于频繁的进行刷新,在流量较高时反而会减轻均匀提早。目前该机制已在线上小范畴灰度,右图展现了灰度后同时间段对应的 write_bytes 指标,能够看到相比左图,数据刷盘速率较灰度前显著平滑,最高速率仅为 40MB/ s 左右。
对于 SSD 新缓存架构,同样存在上述问题,因而在新架构中,在刷盘操作中同样对刷盘速率进行了限度。
计划测试
测试指标
- 验证基于应用层的 SSD 缓存架构可能防止实时作业受到提早作业的影响。
- 验证相比基于操作系统内核层实现的缓存层架构,基于应用层的 SSD 架构在不同流量下读写提早更低。
测试场景形容
- 构建 4 个集群:新架构集群、一般 HDD 集群、FlashCache 集群、OpenCAS 集群。
- 每个集群 3 个节点。
- 固定写入流量,比拟读、写耗时。
- 提早生产设置:只生产绝对以后工夫 10~150 分钟的数据(超过 PageCache 的承载区域,不超过 SSD 的承载区域)。
测试内容及重点关注指标
-
Case1: 仅有提早生产时,察看集群的生产和生产性能。
- 重点关注的指标:写耗时、读耗时,通过这 2 个指标体现出读写提早。
- 命中率指标:HDD 读取量、HDD 读取占比(HDD 读取量 / 读取总量)、SSD 读取命中率,通过这 3 个指标体现出 SSD 缓存的命中率。
-
Case2: 存在提早生产时,察看实时生产的性能。
- 重点指标:实时作业的 SLA(服务质量)的 5 个不同工夫区域的占比状况。
测试后果
从单 Broker 申请提早角度看:
在刷盘机制优化前,SSD 新缓存架构在所有场景下,较其余计划都具备显著劣势。
刷盘机制优化后,其余计划在提早上服务质量有晋升,在较小流量下因为 flush 机制的优化,新架构与其余计划的劣势变小。当单节点写入流量较大时(大于 170MB)劣势显著。
从提早作业对实时作业的影响方面看:
新缓存架构在测试所波及的所有场景中,提早作业都不会对实时作业产生影响,合乎预期。
总结与将来瞻望
Kafka 在美团数据平台承当对立的数据缓存和散发的角色,针对目前因为 PageCache 相互净化、进而引发 PageCache 竞争导致实时作业被提早作业影响的痛点,咱们基于 SSD 自研了 Kafka 的应用层缓存架构。本文次要介绍 Kafka 新架构的设计思路以及与其余开源计划的比照。与一般集群相比,新缓存架构具备非常明显的劣势:
- 升高读写耗时:比起一般集群,新架构集群读写耗时升高 80%。
- 实时生产不受提早生产的影响:比起一般集群,新架构集群实时读写性能稳固,不受延时生产的影响。
目前,这套缓存架构优曾经验证实现,正在灰度阶段,将来也优先部署到高优集群。其中波及的代码也将提交给 Kafka 社区,作为对社区的回馈,也欢送大家跟咱们一起交换。
作者简介
世吉,仕禄,均为美团数据平台工程师。
| 想浏览更多技术文章,请关注美团技术团队(meituantech)官网微信公众号。
| 在公众号菜单栏回复【2019 年货】、【2018 年货】、【2017 年货】、【算法】等关键词,可查看美团技术团队历年技术文章合集。