kafka总结

知识点
1个topic的不同分区中的数据是不一样的。
zookeeper的作用:1.kafka集群选举mater(基于顺序节点,broker.id最小的节点为master)。2.存储分区的副本集信息。

partition
1个partition只能被1个consumer连接(3个partition4个consumer时,有1个consumer会闲置)。
1个consumer可以连接多个partition(2个partition1个consumer时,这2个partition都由这个consumer消费)。
多个producer节点生产消息,如何保证消息的顺序性:生产者把消息按顺序发送到同1个分区,自定义Partitioner,固定的key进指定partition。
ProducerRecord<K, V>:KafkaProducer根据Partitioner算法和这个key计算出这条消息发送到哪个分区上。

group
1个consumer的多个节点消费同1个topic,如何防止重复消费:1个分区只能被1个节点消费。如果1个group下的消费者数量大于分区数,那么多余的消费者节点不会去消费消息。不会出现1个分区被2个消费者节点消费的情况,所以没有并发问题。
多个consumer如何消费同1个topic:通过group.id区分消费者,实现pub/sub广播模式。groupId是消费者的概念,生产者没有groupId的概念。

coordinator
coordinator决定某个consumer消费哪个partition。consumer或partition数量发生变化时,coordinator要rebalance重新分配。算法:range/roundrobin/stricky
消费者的增加和减少,对kafka集群没有影响,也不影响其他消费者消费数据。coordinator负责计算出consumer-leader,rebalance计算每个consumer节点消费哪些分区。consumer-leader负责计算整个consumer集群的分区策略。
如何决定哪个broker是coordinator?coordinator是broker中的1个。

offset
对任意partition来说:消费者offset<=生产者offset
通常在读取记录后,消费者会以线性的方式增加消费者offset。由于这个位置由消费者控制,所以消费者可以采用任何顺序来消费记录。
例如:一个消费者可以重置到一个旧的偏移量,从而重新处理过去的数据;也可以跳过最近的记录,从"现在"开始消费。
持久化机制:broker的__consumer_offsets(也是1个topic)中会保存每个group的所有消费者中最大的offset的值。具体存储在__consumer_offsets-(hash(groupId)%partition数量)这个partition中。

replica
每个topic的副本数量不能超过broker数量。
每个partition都会有1个副本集,副本集都会选举leader副本,leader副本负责处理数据,follower副本负责从leader同步数据。副本信息保存在zk上。
概念
AR:Assigned Repllicas 分区中的所有副本 AR=ISR+OSR
ISR:In-Sync Replicas 所有与leader副本保持一定程度同步的副本。
now-lastCaughtUpTimeMS<replica.lag.time.max.ms,每次同步数据后follower会更新lastCaughtUpTimeMS。
被踢出ISR的副本仍然会进行数据同步,当满足延迟要求后重新进入ISR。
OSR:Out-Sync Relipcas 与leader副本同步滞后过多的副本
leader_epoch:当前分区的leader纪元
logStartOffset:第一条消息的offset
LEO:Log End Offset。每个副本都有自己的LEO。
remote-LEO:leader会保存所有follower的LEO。
HW:High Watermak。只有leader可以更新当前分区的HW。
consumer能够消费到的最新的消息的offset是集群的HW,因为HW之后的消息还没有完成数据同步,副本集数据不一致。HW<=LEO
LW:Low Watermark。
AR集合中最小的logStartOffset值.副本的拉取请求(FetchRequest,它有可能触发新建日志分段而旧的的被清理,进而导致logStartoffset的增加)和删除请求(DeleteRecordRequest)都可能促使LW的增长。
leader副本选举
1.ISR不为空:ISR中的优先副本(第一个副本,数据可靠性比较高)作为leader。
2.ISR为空:如果某个Partition的所有Replica都宕机了,用户配置的unclean.leader.election.enable生效
true:选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader。响应速度比较快。
false:等待ISR中的任一个Replica“活”过来,并且选它作为Leader。可靠性比较强。
集群向producer响应之前,设置acks参数保证至少多少个副本完成同步:0(不需要等任何副本确认,直接响应)/1(leader副本确认)/-1(ISR中所有副本确认)
数据同步:follower向leader发起阻塞式的长轮询请求。fetch是异步复制。replica.fetch.wait.max.ms设置阻塞时间。
情况1.leader处理完producer请求之后,follower发送一个fetch请求过来。请求包含follower的LEO,响应包含leader的HW和新数据。
1.follower发起第一次fetch:
leader收到请求后:
1. 读取log数据、更新remote LEO=0
2. 尝试更新HW,因为这个时候LEO和remoteLEO还是不一致,所以仍然是HW=0
3. 把消息内容和当前分区的HW值发送给follower副本
follower副本收到响应后:
1. 将消息写入到本地log,同时更新follower的LEO=1
2. 更新follower HW,本地的LEO和leader返回的HW进行比较取小的值,所以仍然是0
2.follower发起第二次fetch:
leader收到请求以后:
1. 读取log数据
2. 更新remote LEO=1, 因为这次fetch携带的LEO是1.
3. 更新当前分区的HW,这个时候leader LEO和remote LEO都是1,所以HW的值也更新为1
4. 把数据和当前分区的HW值返回给follower副本,如果此时leader没有新数据,则返回的数据为空
follower副本收到响应后:
1. 如果有数据则写本地日志,并且更新LEO
2. 更新follower的HW值为1:此时数据的同步就完成了,意味着consumer能够消费offset=1这条消息了。
情况2.follower阻塞在leader指定时间之内,leader副本收到producer的请求,leader会唤醒处于阻塞的fetch请求。
消息丢失
情况1:min.insync.replicas=1且acks=1的情况下,follower崩溃恢复后会截断数据,同步数据时leader挂了,follower为新leader,老leader变为follower,向新leader同步数据后截断自己的数据。这样2个副本都截断了数据,该分区发生数据丢失。可以通过leader-epoch解决,follower崩溃恢复后先向leader发送OffsetForLeaderEpochRequest确认是否需要截断数据。
情况2:follower数据落后于leader,leader挂了后一直没恢复,follower当选为新leader,老leader中的数据就丢失了。这种情况没办法解决。

消息积压
1.生产者过滤。
2.消费者关闭自动提交,批量消费到500条消息后丢到本地队列立刻提交,然后去获取下一批消息。
3.多个异步线程去再去本地队列中取消息进行真正的业务处理。
4.优化业务处理流程,先尽快发送出去后,再异步保存消息记录到DB。
5.实时性要求高的动账消息只进一次消息队列。

消息存储
分段存储:log.segment.bytes:设置分段大小,默认是1gb。
每个segment都有xxx.log和xxx.index文件。
xxx.log中第1条消息的offset作为文件名。消息的position是物理偏移量,表示ByteBuffer的指针位置。消息的payload就是消息内容。
xxx.index保存了部分消息的offset和position对应关系。kafka采用稀疏索引的方式来提高查找性能。
根据offset定位到某条消息:
1. 根据offset值,使用二分查找定位到index索引文件。
2. 根据offset进行定位,找到索引文件中的符合范围的某个索引的position。
3. 在对应的log文件中,从position处开始查找目标offset对应的消息,将每条消息的offset与目标offset进行比较,直到找到消息。
磁盘存储如何保证性能:
1.顺序写
2.零拷贝
3.页缓存
1.read:当一个进程准备读取磁盘上的文件内容时,操作系统会先查看待读取的数据所在的页(page)是否在页缓存(pagecache)中,如果存在(命中)则直接返回数据,从而避免了对物理磁盘的I/0操作;如果没有命中,操作系统会向磁盘发起读取请求并将读取的数据页存入页缓存, 之后再将数据返回给进程。
2.write:同样,如果一个进程需要将数据写入磁盘,那么操作系统也会检测数据对应的页是否在页缓存中。如果存在则直接修改页缓存。如果不存在,则会先在页缓存中添加相应的页,最后将数据写入对应的页。被修改过后的页也就变成了脏页,操作系统会在合适的时间把脏页中的数据写入磁盘,以保持数据的一致性

消息清理
1.过期清理:log.retention.hours(消息的保留时间)/log.retention.bytes(topic存储的数据大小)
2.日志压缩:定期将相同的key进行合并,只保留最新的value值。----是否会影响业务?

消息可靠性
1.确保消息从producer发送到broker:acks。批量发送+定时发送。
2.broker确保消息不丢失:分区副本机制。
3.确保consumer消费到消息:自动提交/手动提交。
自动提交可能会造成消息丢失:consumer取到消息丢到本地队列后,时间到了自动提交,但是还没处理就挂了,这些消息就丢失了。
手动提交可能会造成重复消费:consumer取到消息后挂了,这批消息就一直没有提交,consumer启动后重新从kafka消费这些消息。应用可以通过幂等性解决重复消费的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值