Kafka
kafka是一个基于事件流的分布式系统,通过TCP网络协议进行通信.
- kafka设计所追求的特点
- 具备高吞吐量
- 处理大型的数据积压工作,支持离线的数据加载
- 需要支持低延迟的交付
- 在系统出现问题时,具有一定的容错机制
- kafka的基本概念
- Broker:kafka集群中的服务器
- Topic:事件的类别由Topic区分
- Partition:Topic的物理分区,一个Topic可以具备多个Partition,每个Partition为每一条事件都分配了有序的ID(offset)
- Producer:消息的生产者,往kafka推消息
- Consumer:消费的消费者,往kafka取消息
- ConsumerGroup:每一个消费者都属于一个ConsumerGroup;每个ConsumerGroup只会把消息发送给一个Consumer;通过配置Consumer以及ConsumerGroup来完成单播、广播
- kafka基础示意图:
- kafka中Topic与Partition的关系:
- kafka中的分区(Partition)
- kafka的分区作为基本的存储单元,每个Partition拥有多个Segment;每个Segment一个数据文件以及与之对应的索引文件
- 每一个Partition的message都具有一个顺序的ID
- kafka中的Partition可以位于不同的机器上;所以Partition的数目极大的影响力kafka的并行处理能力
kafka的高吞吐量可以从几个方面分析
- kafka的实现方式:kafka基于scala实现的,由于JVM的FULLGC影响,如果将数据存储在内存中,将极大的降低性能 ;因此kafka采用的方式并不是在内存中构建缓存,而是基于操作系统本身的文件系统以及页面缓存来实现的
- 网络带宽: kafka消息发送支持批量发送,同时对于批量发送的消息支持批量压缩
- 持久化:
- kafka的消息持久化队列采取的顺序写入的方式进行的(有序IO),类似于日志记录; ,对于有序IO,操作系统对于有序IO可以进行大量的优化
- kafka的持久化策略通过直接写入内核态的页面缓存中(文件系统的持久化日志),由操作系统决定何时刷入盘;而不是尽可能地写入内存,然后再刷新到文件系统
- 消息读取
- 零拷贝: 技术的使用。通过减少操作系统内核态、用户态的切换次数以及同一份数据的拷贝次数来提升性能
- 网络请求:
- Reactor模式:
通过Reactor模式将连接的初次建立、业务处理解耦;同时通过线程池提高业务执行的并行度
kafka如何保证消息的可靠性?
kafka保证Producer到Broker的消息可靠性通过三个方面实现;
1.消息的发送方式;2.消息的确认方式;3.消息的重试机制
- 消息发送方式
- 直接发送(不关注消息发送的结果)
- 同步发送(关注发送的结果,获取Future实现获取结果)
- 异步发送(关注发送的结果,同时也在乎Producer的性能,通过回调函数实现)
- 消息确认方式
- 不等待Broker确认(性能最优,不保证投递的可靠性)
- 由leader确认,leader确认投递成功,则成功;不考虑follower的投递成功性(由follower异步拉去leader,折中的实现方式)
- 由所有的leader,follower确认成功后才认为投递成功(保证最强的可靠性,但是性能损耗较高)
- 消息重试机制
- kafka对Producer提供了重试机制;当重试次数达到上限时,会直接返回异常
消费策略
消费者组是kafka为了保证系统可拓展,容错性的消费机制;一条消息只能被一个消费者组的一个消费者消费
- 消费者的单播与广播
- 单播指把所有consumer置于一个consumerGroup中;广播指把每一个consumer置于不同的consumerGroup
- 消费者的推拉机制
- 推机制:由Broker推消息给Consumer;优点是消费的实时性较好,缺点是无法考虑消费者的消费速度,可能导致消费者崩溃
- 拉机制:由Consumer拉取Broker;优点是拉取的速度由Consumer决定,可以保证Consumer的可靠性;但是无法保证消费的实时性
- 再均衡机制
- kafka的一种负载均衡手段,本质是保证消费者组下的所有消费者如何达成一致分配topic下的Partition
- 当consumer发生变更;Partition发生变更;topic发生变更时触发再均衡
- 再均衡机制保证consumer的可用性;但是会影响性能
消费者偏移量
前面提到kafka中分区的消息都是有序的,因此kafka中只需要一个offset就可以控制消费的位置;
kafka中存在一个特殊的topic(_consumer_offset)保存各个分区的offset
- 如何保证消息消费的可靠性?
kafka中通过commit来提交offset,保证消费的可靠性;而commit具有三种策略;分别是自动提交,手动提交,异步提交
- 自动提价通过kafka定期(默认是5S)提交offset;
- 优点是简单
- 缺点是容易导致重复消费;如果再消费完之后的第2S,消费者发生异常,没有commit,则下次会重复消费这2S的消息
- 手动提交
- 优点:可以保证消息的可靠性,也能保证消息不被重复消费,具备commit失败,重试机制
- 缺点:手动提交会阻塞线程,直到commit成功,或者抛出异常;因此这十分影响吞吐量、性能
- 异步提交
- 优点:不会阻塞当前线程,无需等待broker的回复
- 缺点:没有重试机制,可能导致消息的消费丢失,已经提交commit,但是consumer崩了;如果 ;如果commitA的offset为100,commitB的offset为200;但是commitA网络延迟了,commitB已经提交,此时commitA到达broker,则offset会由200-> 100,依然会导致重复消费问题