1,kafka基本组成:
broker:一个kafka节点就是一个broker,多个broker组成集群,用于存储消息和处理消息。
topic:一个broker下有多个topic主题,每个消息都需要指定一个topic,用于消息归类。
producer:消息生产者,用于给broker发送消息。
consumer:消息消费者,用于读取broker的消息。
consumergroup:消息群组,每个消费者都需要指定消费组,一个消息可以发给多个consumergroup,但是同一个分区内的消息只能有一个分组内的一个消费者消费。
partition:物理概念,一个topic下有多个partition,多个partition分布在不同的broker下,每个partition内的消息是有序的。
2,kafka强依赖于zk。
3,消息模式:
单播消费:一条消息只能为一个消费者消费,消费者存在于一个消费者组内就可以实现,一个组内的消息只能由一个消费者消费。
多播消费: 一条消息可以给多个消费者消费,消费者存在于多个消费者组内就可以实现,多个组的消息可以由多个组的消费者消费。
4,分区,一个主题下可以有多个分区,一个分区保存数据是有序的,一个分区对应一个commit log文件,分区中数据通过offset对应。
kafka不会删除消息,不管消息有没有被消费,都会默认保留1周的时间,可以设置,一周后自动删除。
每个consumer都是基于自己在commitlog中的消费进度(offset)来进行消费的。消费的offset是由consumer消费者维护的,因此增加多个消费者对kafka性能没有影响。
分区可以解决数据量较大的时候,把多个分区存储在不同机器上。
5,集群搭建,复制多个配置文件,修改id和端口。
每个broker下多个分区,分区有leader和follow得概念,broker没有这个概念。
一个主题下得分区可能分布在不同得broker下。
一个分区只能被一个消费者组内的一个消费者来消费,不能一个分区对应一个组内得多个消费者。
多个消费组消费一个分区消息可以都消费到。也就是一个分区可以给多个消费者组来消费。
一个消费者组内得消费者不能接收到一个分区内的消息。
6,顺序消息
可以使用一个topic下一个分区对应一个消费者组内的一个消费者实例,从而达到顺序消费。性能低。
7,消息ACK确认和消息持久化机制
acks = 0:意味着消息发送给kafka只会不管有没有接收到,更不管其有没有持久化,直接发送下一条,容易丢消息。
acks = 1:意味着消息发送给kafka的某个topic下的leader分区后,leader持久化完成后,在进行发送下一条消息。默认使用这个。
acks = -1或者all:意味着消息发送给kafka的某个topic下的leader分区后,leader和follower都持久化完成后,在进行发送下一条消息,用于金融业务,防止丢消息,但是影响性能。
8,消息发送失败后重试
retries可以设置重试次数,retry.backoff.ms设置间隔时间。
由于网络抖动导致消息重发发送,需要在客户端进行消息的幂等性处理,kafka新版本支持kafka识别重复消息防止重复发送。
9,高并发下大数据量发送支持客户端缓冲区。
buffer.memory:放置发送消息的本地缓冲区,如果设置了该缓冲区,消息会先发送到本地缓冲区,可以提高消息发送性能,默认值是33554432,即32MB。
batch.size:消息批量发送给kafka,一次批量发送的大小。
linger.ms:默认值是0,意思就是消息必须立即被发送,但这样会影响性能,一般设置10毫秒左右,就是说这个消息发送完后会进入本地的一个batch,如果10毫秒 内,这个batch满了16kb就会随batch一起被发送出去,如果10毫秒内,batch没满,那么也必须把消息发送出去,不能让消息的发送延迟时间太长
10,kafka数据日志存储:log,index,timeindex
log存放的是按顺序记录的所有消息
index存放的是消息的offset
timeindex存放的是消息的时间索引。
11,手动提交offset,自动提交offset(默认),可以设置自动提交offset间隔时间。
12,客户端一次消费消息数量,如果一定时间没有消费完成,则将消费者踢出消费群组。
heartbeat.interval.ms:消费者发送给broker的心跳间隔,每过多久发送一次心跳。
session.timeout.ms:服务端broker多久感知不到一个consumer心跳就认为他故障了,会将其踢出消费组,并触发rebalance,将分区给其他消费者消费。
max.poll.records:一次poll最大拉取消息的条数,如果消费者处理速度很快,可以设置大点,如果处理速度一般,可以设置小点
max.poll.interval.ms:如果两次poll操作间隔超过了这个时间,broker就会认为这个consumer处理能力太弱,
会将其踢出消费组,将分区分配给别的consumer消费
13,消费者可以指定分区消费,
可以指定消息发送时间消费,先将时间转换为offset,再按照offset进行消费,
可以指定offset消费。
14,当消费主题的是一个新的消费组,或者指定offset的消费方式,offset不存在,那么应该如何消费
auto.offset.reset:latest(默认) :只消费自己启动之后发送到主题的消息
auto.offset.reset:earliest:第一次从头开始消费,以后按照消费offset记录继续消费,这个需要区别于consumer.seekToBeginning(每次都 从头开始消费)
15,broker集群下controller选举:kafka启动时,每个broker会往zk创建controller临时节点,第一个创建成功的broker就成为controller。
16,分区下的leader选举,当分区leader挂了,controller通过监听机制会感知到变化,controller从ISR中选取第一个作为leader,如果第一个也挂了,则选第二个。以此类推。
17,kafka线上环境规划。
1,消息丢失情况:
消息发送端设置ack级别:0,1,-1/all
消息消费端设置提交offset为手动提交,自动提交可能导致业务没有处理完消费端挂了,导致丢消息。
消息服务端设置同步刷盘的持久化方式
2,消息重复消费情况:
消息发送端配置了重试机制,ack反馈的时候网络抖动,会导致消息重复消费。
消息消费端配置了自动提交,消费端收到消息还没来得及提交服务挂了,下次重启还会发送这些消息导致重复消费。
解决方案:在消费端进行消息幂等性,例如,联合主键、分布式锁,key设置了就无法再进行处理了。
3,消息顺序消费:
消息生产者:一定要设置同步发送,一条发送成功再发送下一条。异步发送可能第一条消息发送失败,重试过后已经排在其他消息的后面了。一定要保证发送给一个主题下的一个分区内。
消息消费者:务必要保证消费在一个分区下的消息。
如果既想消息顺序,又保证性能消息分发到多个分区,可以在生产者发送前给数据加个type标识,消费者收到后,通过CountDownLatch将消息都受到后统一进行排序处理。
4,消息积压解决方案:
1,消息先存入数据库或缓存,再慢慢处理。
2,消息接收到以后转给其他topic下的多个分区,再启动多个消费者进行消费。
5,消息延迟队列方案:
1,将消息发送给不同时间段的topic,定时器轮询消费这些消息,判断消息是否到期,到期的话就消费,没到期就不消费。
6,kafka事务方案:
kafka开启事务,将消息发送给不同的主题下的不同分区,提交事务
消息发送要么都成功要么都失败。
7,kafka高性能原因:
1,磁盘顺序读写
2,数据传输的零拷贝
3,读写数据的批量batch处理以及压缩传输