Kafka集群被大量用来对流量高峰期限流、系统解耦合、削弱峰值等业务场景。Kafka提供了高性能的消息写入、持久化、读取的优化。每一种技术都不能解决所有的问题。
本文整理自快手高级架构师、大数据架构团队负责人赵健博在 QCon 全球软件开发大会(北京)2019 上的演讲,他介绍了 Kafka 系统在快手的应用实践、遇到的问题以及相应的技术的演进过程。
数据规模
日处理消息级别:万亿
峰值:1亿/s
集群类别
kafka作为消息中间件
不同业务之间提供消息通知服务
LOG集群
业务程序将Log打给kafka
离线集群
- 数据实时dump到hdfs
- 为实时计算提供数据源
- 为实时训练提供数据源
解决的问题
对borker的平滑扩容
问题:
系统需要新增一个borker时,如何平滑的将现有的topic平滑的迁移到新的broker上,从而实现topic的leader和follower的均匀分布?
解决:
1、在新的broker上创建副本用于迁移源topic(或其中一个副本),
2、读取的时候从最新的offset开始读
- 从最新的offset开始读,可避免大量I/O
- 有些已经消费过的数据后续不会用到,没有必要迁移
3、保持一段时间,当所有的consumer都消费到开始读取的offset,即可删除源数据,迁移完成。
Mirror的集群化
kafka Mirror是kafka为集群的数据迁移提供的一个解决方案
Kafka Mirror 存在的问题:
1、静态管理,维护成本高、易出错
- topic 数量
- Mirror机器列表
2、变更操作导致整体断流
- 增减 topic
- 机器扩容或缩容
解决:
基于 UReplicator,开发了 KReplcator 服务,并替换掉了现有的 MirrorMaker 服务。UReplicator 是 Uber 开源的 Kafka 数据 Mirror 同步服务。
KReplcator 集群包含三个模块:
- Controller: 动态管理 topic、worker 的增减
- worker:数据的传输
- zookeeper:协调Controller与worker
资源隔离
问题1:
同一个业务线的topic分布在不同的broker上,不同业务线的topic分布在broker上,如果consumer出现问题,导致消费产生lag,lag积累会造成磁盘繁忙,影响其他业务线。
解决:
物理隔离,把不同的topic放到不同的broker,尽量减少业务线的交叉
- 创建topic
- 迁移topic
- 宕机恢复流程
问题2:
kafka PRC 队列缺少隔离,某个topic慢,会导致所有请求hang up
解决:
分拆多个PRC队列,队列隔离
cache改造
Kafka 之所以有如此高的性能,主要依赖于 page cache,producer 的写操作,broker 会将数据写入到 page cache 中,随后 consumer 发起读操作,如果短时间内 page cache 仍然有效,则 broker 直接从内存返回数据,这样,整体性能吞吐非常高。
问题:
1、comsumer的lag读会对 page cache 产生污染
2、follower 会造成 page cache 污染,follower写入的数据是一次性的,后续不会在被读取,所以缓存没有必要
解决:同时写两个对象
- block cache: block cache 中的数据全都是 producer 产生的
- flush queue: flush queue 中的数据会由其他线程异步地写入到磁盘中
对于 consumer 而言,在 broker 接到消费请求后,首先会从 block cache 中检索数据,
如果命中,则直接返回。否则,则从磁盘读取数据。这样的读取模式保障了 consumer 的
cache miss 读并不会填充 block cache,从而避免了产生污染,
即使有大 lag 的 consumer 读磁盘,也仍然保证 block cache 的稳定。
智能限速
问题:
consumer lag 导致producer写入受阻?
解决:
- 思路:当磁盘繁忙,针对lag的consumer进行限速控制
- 添加限速模块,包含lag域值检测、限速策略、信息采集,延迟队列等