kafka2.4之后,kafka提供了有限的读写分离,也就是说follower副本能够提供读服务
之前没有,因为读写分离适用于读负载很大,而写操作相对不频繁的场景.可kafka不属于这样的场景
同步机制:kafka采用pull 方式实现follwer的同步,因此Follwer与leader存在不一致性窗口,如果允许读follwer副本,就势必要处理消息滞后的问题
生产者发送到broker里面的策略和流程是怎样的?
.如果指定partitionId 则PR被发送到指定partition
如果未指定id,但指定了key,PR会按照hash发送到对应partition
如果两者均为指定.PR会按照round-robin轮训模式发送到每个partition
2.kafka的客户端发送数据到服务器,先经过内存缓冲区默认16KB,通过kafkaProducer发送出去的消息都是先进入到客户端本地的内存缓冲区中,然后把很多消息收集到batch里面,再一次性发送到broker上去的,这样性能才可能提高。
3.发送的send方法是异步的,添加消息到缓冲区等待发送,并立即返回。
生产将单个消息批量在一起发送来提高效率,一条消息发送之后,会阻塞当前线程,直至返回ack,发送消息后返回的一个future对象,调用get方法
消息发送主要有两个线程,main线程和sender线程
4.main线程发送消息到recordAcuccmulator返回
sender线程从recordAccmulator拉取信息发送到broker,发次数主要受batch.size和linger.ms两个参数影响
消费者消费机制和分区策略
1.消费者采用pull拉取方式,从partition获取数据
pull模式可以根据consumer的消费能力进行自己调整,不同的消费者性能不一样,如果broker没有数据,comsumer可以设置超时时间,阻塞等待一段时间再返回.
如果是broker主动push,优点是可以快速处理消息,但是容易造成消费者处理不过来,造成消息堆积和延迟
2.消费者从哪个分区进行消费?
a.顶级接口org.apache.kafka.clients.comsumer.internals.AbstractPartitionAssignor
b.按照消费者组进行轮训分配,同个消费者组监听不同主题一样,把所有partition和comsumer列出来,订阅主题不一样导致分配不均
c.rangeAssignor默认策略,按照主题进行分配,如果不平均分配则第一个消费者会分配的比较多
自动提交offset问题?
1.没法控制消息是否正常被消费
2.适合非严谨的场景,比如日志收集发送
手工提交offset配置
1.初次启动消费者会去broker获取当前消费的offset的值.
2.同步commitSync阻塞当前线程,自动失败重试.
3.异步commitAsync不会阻塞当前线程,没有失败重试,回调callback函数获取提交信息,记录日志
kafka之间副本数据同步是怎样的?一致性怎么保证,数据怎样保证不丢失呢?
我主要从以下三个方面解释:
a.producer端:
保证生产者发送到指定的topic,topic下的每个partition收到发送数据后需要向producer发送ack确认收到,就会进行下一轮的发送否则重新发送数据
broker端(消息存储的可靠性):
1.kafka副本,一个topic下设置多个副本,副本数量小于broker数量.每个分区有一个leader和0到多个follwer,
replica分为leader replica 和follwer replica
2.副本间数据同步机制
当producer在向partition发送数据,根据ack机制,默认
ack=1,只会向leader中写入数据,并且接收,而且写入本地磁盘,不管其他follwer然后返回ack.然后leader中的数据会复制到其他replica中,follwer会周期性的从leader中pull数据。
存在的问题? leader接收到消息还没有同步给follwer此时leader所在broker挂了。
ack=0,producer发送一次就不再发送,不管是否发送成功,
存在的问题?如果中途broker挂了消息存在丢失
ack = -1或者all,producer只有收到分区内所有副本写入成功才会认为消息推送成功
存在问题?
a .follwer同步完成后,broker发送ack之前,leader发生故障,会造成数据重复.
b. ack=all 就可以代表数据一定不会丢失吗?
1.partition只有一个副本,也就是leader本身,任何follwer都没有
2.接收完消息后宕机,也会导致数据丢失,ack=all,必须跟isr列表至少有2个以后的副本配合使用
在设置ack=-1的同时,也要min.insync.replicas这个参数设定isr的最小副本是多少,默认是1,如果isr中的副本数量小于配置值,客户端会返回异常.
每一个leader partition 都有一个isr,leader动态维护,要保证kafka不丢失message,就要保证isr这组集合存活,并且消息commit 成功,
当ISR中的partition follwer完成数据同步之后,就会给leader发送ack.如果follwer长时间未向leader同步数据,则该partition follwer将被提出ISR
leader发生故障之后,就会从isr中选举新的leader
即在静态方法中不能引用非静态方法
因为我们知道静态的方法可以在没有创建实例时使用,而申明为非静态方法是一个对象的方法,它只有在对象存在时调用,因此如果在对象未创建实例时我们在静态方法中调用了非静态方法自然是非法的,所以编译器会在这种时候给各错误.
consumer端:
hw,保证消费数据的一致性和副本数据的一致性,指所有副本中最小的leo.
follwer故障:首先临时剔除ISR,待该follwer恢复后,读取本地的记录的hw,把该log文件高于hw部门截取掉,从hw开始向leader进行同步,等该follwer的leo大于等于该partition的hw,即follwer追上leader后,重新加入ISR.
leader故障:leader发生故障后,会从ISR中选出新的leader,为了保证多个副本数据的一致性,其余的follower会先将各自的log文件高于hw的部分截取掉,新leader不会截取,然后从新leader同步数据
kafka日志清理策略:
背景:数据持久化到磁盘上,为了控制磁盘容量,需要对过去的消息进行清理。
1.内部有个定时任务定期检查删除日志,默认是5分钟。
2.基于时间删除
每个日志段文件都维护一个最大时间戳,每次新写入消息时,都会更新该字段,一个segment日志段写满后,不再接收消息,最大时间戳字段保持不变。
kafka通过将当前时间与该最大时间戳进行比较,判断是否过期
3.基于大小超过阈值
超过阈值的部分必须大于一个日志段的大小。
4.日志压缩
log.cleanup.policy=compact启用压缩策略
按照消息key进行整理,相同key不同value只保留最后一个
有讲错希望大家指出来谢谢