kafka定义
- kafka是分布式的基于发布/订阅模式(一对多,消费者消费消息之后不会被清除)的消息队列
kafka基础架构
-
–producer:生产者,生产消息到topic
-
–consumer:消费者,从topic中消费消息
-
–broker:kafka集群中,每台服务器就是一个broker
-
–topic:消息逻辑上以topic形式,物理上以partition存放,每个topic可有多个partition,每个partition有多个replication(一个leader,多个follower)
说明:
一个topic的多个partition可分布在同一个或不同的broker上,一个partition的replication不可以分布在同一个broker上
生产者生产数据,消费者消费数据的对象都是leader,follower仅用于同步leader中的数据 -
消费者消费消息原则:
一个消费者组中的一个消费者可以消费多个分区,但一个分区只能被每个消费者组中的一个消费者消费
即:一般消费者组中一个消费者对应一个分区 -
–zookeeper作用:
(1)kafka集群启动后,每个broker向zookeeper注册并争抢确定controller,controller负责topic,partition,relpication等的增删改
(2)topic等信息保存在zookeeper中,可通过zookeeper使用他们 -
注:kafka中专门有一个topic用来记录每个consumer读取到队列中哪一条消息(offset),防止当前consumer挂掉时,其他consumer可继续从上次消费位置继续
kafka工作流程
-
1. 首先说明下消息在kafka上是怎样存储的:
producer生产的消息逻辑上是面向topic的,但物理上是存放在topic中的partition的,每个partiton中有一个log文件,该log文件由多个segment组成(实质就是多个log文件(每个log文件默认配置1G)),每个segment都由一个index文件和log文件组成:
index文件:存放消息位置的索引
log文件:存放消息如下图:log中的每条消息都有自增来的编号,index文件中对每条消息编号有对应的消息起始位置,比如想要找offset为3的数据,从index中可知道其在log中的起始位置为756,所以直接进log文件从756开始读取即可
-
2. kafka工作流程
-
–(1)producer按照分区原则将消息放入指定分区的log文件中(log文件末尾追加形式)
-
–(2)log文件中每条数据都有自己的offset值,index文件中也会保存每个offset的索引
-
–(3)consumer消费数据时就根据index文件中的offset索引去log文件中消费数据,且每次消费都会实时记录自己消费到了哪个offset消息(存放在专门的topic中)
producer
- 分区原则
将producer发送的数据封装成一个ProducerRecord对象
1)当指定分区号:消息发送到指定的分区
2)当未指定分区,而指定Key:按照key的hashcode值%分区数
3)当没有指定分区和key:
在kafka低版本中:轮询
当前版本中:黏性分区,首先随机一个分区,然后黏住该分区,
直到该分区对应的batch满(默认16KB)或超时(1ms),会将batch中的数据发往分区,
之后再次随机一个新(本次刚用完的排除)的分区黏住使用
-
生产数据可靠性
为保证producer生产的数据可靠得传输到topic,当topic分区收到消息并同步给所有follower后,会给producer返回ack
-
1)producer发送数据的可靠性
kafka要求所有follower同步完数据后,才向producer发送ack确认消息,但是这样效率会低,个别副本出问题就不会发ack,此时则用到ISR副本同步列表
-
2)ISR同步列表
ISR同步列表,存放所有leader+follower,
当超过一定时间某个follower还没同步成功,就会将其踢出集合,然后回复ack,
踢出的follower继续与leader同步数据,当同步leader后,就会重新进入ISR集合 -
3)ack可靠性应答级别
0: leader接收消息未写入磁盘就回复ack,可能丢失数据
1: leader落盘但follower未同步成功就回复ack,可能丢失数据
-1(all): leader及所有follower数据落盘后回复ack,可能造成数据重复 -
4)Exactly Once:(解决ack=-1时数据重复问题)
0.11 版本的Kafka,引入了一项重大特性:幂等性。
所谓的幂等性就是指Producer不论向Server发送多少次重复数据,Server端都只会持久化一条
实现方式:
Broker端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时, Broker只会持久化一条。
问题:幂等性无法保证跨分区跨会话的Exactly Once。 -
5)LEO和HW:消费者消费消息时,只从Leader消费
LEO:指的是每个副本最大的offset;
HW:指的是消费者能见到的最大的offset,ISR队列中最小的LEO。
leader或follower故障后都是从HW开始重新同步,log中高于HW之后的会删掉,重新从leader的HW往后开始同步
Consumer
-
消费方式:拉取
-
1.分区策略
1) Round Robin 轮询:
2)Range 范围(均分)
3)黏性 -
2.offset维护
1) Kafka 0.9版本之前,consumer默认将offset保存在Zookeeper中,
从0.9版本开始,保存在Kafka一个内置的topic(__consumer_offsets)2) 维护方式GTP(消费者组,主题,分区),保证换了消费者后换可以接着之前的消费,
记录的是下一个要消费的offset
Kafka高效读写原因
1)顺序写:末尾追加,省去了大量磁头寻址时间
2)分区:提高并行度
3)页缓存,零复制技术等技术
-
zookeeper在kafka中的作用:
Controller确定,leader的选举等都依赖于zookeeper
-
Kafka事务:
解决幂等性存在的跨分区跨会话数据依然可能重复的问题
事务ID与PID绑定,Producer重启后可通过事务ID找到PID -
精准一次性消费:
漏消费和重复消费问题,将消费和提交绑定,放到事务中