生产者分区的原则
分区的意义
-
提升了水平扩展能力
-
提供并发能力
分区的原则
-
指明partition的情况下,直接将指明的值作为partition的值(指定存放分区)
-
没有指明partition,但有key的情况下,会将key的hash值与topic的partition数量进行取余得到partition值
-
什么都没有指定,在第一发消息的时候,系统会随机生成一个整数来对topic的partition数量进行取余得到partition值,后面每次都对这个已经生成的随机数进行+1,这就得到了round-robin算法了
Kafka副本的复制方案
Kafka内部发送响应的机制:为了保证producer的数据能够可靠的发送并保存到topic上,topic的每个partition收到发送的数据后,都需要向生产者发送ACK,如果生产者收到ACK,就会进行下一轮发送,如果没有收到就会重新发送。
副本的复制方式:Producer--->leader(follower1,follower2)。向Producer发送ACK有以下两个方案:
- 确保半数以上的follower完成同步,就发送ACK,优点是延迟低,在选举新的leader的时候,如果容忍n台节点故障,就需要2n+1个副本
- 完成全部follower的同步,才发送ACK,缺点是延迟高,在选举新的leader的时候,如果容忍n台节点故障,只就需要n+1个副本
kafka使用方案二作为follower的同步方式
-
如果选择方案一:虽然网络延迟低,但数据一致性无法保障,而且需要2n+1个副本,副本过多就会导致数据冗余过大,造成很大浪费
-
虽然方案二延迟高,但对于kafka来说影响不大
通过ISR优化副本同步
在kafka采用第二种方案进行副本复制后进行ACK响应,会等待所有follower完成同步,这个时候如果有一个follower因为某种原因无法访问,这个时候leader就要一直等着这个follower来完成同步才能发ACK给producer。Kafka的解决方案:Leader维护了一个动态的in-sync replica set(ISR)
-
副本同步机制
-
作用是和leader保持同步的follower集合
-
当ISR中的follower完成数据同步之后,leader就会给follower发送ack(数据是由follower主动从leader那里拉取过来的)
-
-
ISR是一个动态同步集合:从ISR中移除follower的条件是当follower长时间未向leader拉取数据,该follower就会被剔除出ISR,时间阀值由:replica.lag.time.max.ms=10000 决定 单位ms
-
当leader发生故障了,就会从ISR中选举新leader
Kafka生产者的ACK机制
kafka是利用ACK机制来保证可靠性的,流程是producer发送给broker-->partition(leader)-->replication(2)
producer通过一个配置项目ACKS完成生产者的ACK机制
-
acks = 0 : producer只要给到broker就返回ack,当broker接收到数据后,如果broker故障导致数据丢失
-
acks =1 : partition的leader落盘成功后才返回ACK,不关心follower,当我们的partition的leader挂掉后数据就无法同步到follower(leader挂了,要选举生成新的leader)
-
acks = -1 : 所有ISR中的分区都同步成功才会返回ACK给producer
kafka的producer在没有接收到ACK后会重试,这个重试是有次数的,次数可以配置。
Kafka分布式保存数据一致性问题
producer有一个重试机制,如果数据没有接收到ACK的情况下,重新再次发送。
介绍两个概念:
LEO(Log End Offset):每个副本最后一个offset
HW(High Watermark):所有副本中最小的那个LEO
保持数据一致性的执行过程:
1、follower故障
follower发生故障就会被剔除出ISR,待follower恢复后,follower会读取本次磁盘上上次记录的HW,将log文件中高于HW部分截取掉,从HW开始向leader进行同步,待follower的LEO大于等于Partition副本的HW,当follower追上leader以后,就可以重入ISR
2、leader故障
leader故障之后,会从ISR中选一个follower成为leader,为保证多个副本间的数据一致,将所有的副本各自的高于HW的数据部分截取掉,从新的leader同步数据
注意:这个只能保证数据一致性,不能保证数据不丢失或者不重复
Kafka的Exactly Once实现
将producer的ack设置为-1,保证数据producer到partitons的数据不丢失,也就是At Least Once,如果将ack设置为0,可以保证每条消息只会发送一次,即At Most Once
At Least Once可以保证数据不丢失,但不能保证数据不重复,At Most Once可以保证数据不重复,但不能保证数据不丢失
Exactly Once = At Least Once + 幂等性
At Least Once 可以通过Producer的ACKS设置为-1来解决,在kafka的v0.11(含)之后引入了一个新特性:producer端的幂等性,无论Producer发给broker多少次,只要数据重复,broker只会持久化一条给到topic
在Producer端通过参数 enable.idempotence 设置为true即可,相当于开起了producer端的幂等性:Producer在初始化的时候会被分配一个PID,发往同一个Partition的消息会附带Sequence Number。broker端会对<PID,Partition,Sequence Number>做主键缓存,当有相同主键信息只会持久化一条了
但是:系统只要重启就会更新PID,在不同的Partition上会有不同的主键,所以Producer的幂等无法保证跨分区跨会话的Exactly Once
Kafka生产者的事务机制
kafka的数据可以有很多的partition
场景:当producer个p0,p1,p2写入数据,0-10,1-15,正要给2分区写数据broker挂了,如果acks=1,有主分区没有写入完成,producer会重试发送
在kafka的v0.11版本引入了transactionID,将transactionID和PID绑定并保存事务状态到一个内部的topic中,当服务重启后该事务状态还能正常获取。
来源:oschina
链接:https://my.oschina.net/u/4080405/blog/4289299