Kafka原理综合

kafka2.4之后,kafka提供了有限的读写分离,也就是说follower副本能够提供读服务

之前没有,因为读写分离适用于读负载很大,而写操作相对不频繁的场景.可kafka不属于这样的场景

同步机制:kafka采用pull 方式实现follwer的同步,因此Follwer与leader存在不一致性窗口,如果允许读follwer副本,就势必要处理消息滞后的问题

Kafka数据存储流程

Partition

一个有序的队列,以文件夹的形式存储在具体broker本机上

leo

表示每个partition的log最后一条message的位置

hw

表示partition各个replicas数据间同步且一致的offset位置,即表示allreplicas已经commit的位置

hw之前的数据才是commit后的,对消费者可见

ISR集合里面最小的leo

offset

Segment

ISR:partition leader会维持

Kafka高效文件存储设计特点:

kafka采用分片和索引机制,将每个partition分为多个segment

索引文件并不是为每条message建立索引,而是采用了稀疏存储的方式

即每隔一定字节的数据建立一条索引,避免索引文件占用过多空间和资源,从而可以将索引文件保存在内存中

缺点:没有建立索引的数据需要进行小范围的顺序扫描操作

Kafka把topic中一个partition大文件分成多个小文件段,通过多个小文件段,就容易定期清楚或删除已经消费完文件,

减少磁盘占用

通过索引信息可以快速定位message

producer生产数据要写入log文件中,写的过程是采用追加文件末尾的方式为顺序写

生产者发送到broker里面的策略和流程是怎样的?

1.如果指定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两个参数影响

消费者消费机制和分区策略

消费者根据什么模式从broker获取数据?(消费者机制)

1.消费者采用pull拉取方式,从partition获取数据

pull模式可以根据consumer的消费能力进行自己调整,不同的消费者性能不一样,如果broker没有数据,comsumer可以设置超时时间,阻塞等待一段时间再返回.

如果是broker主动push,优点是可以快速处理消息,但是容易造成消费者处理不过来,造成消息堆积和延迟

2.消费者从哪个分区进行消费(分区策略)?

a.顶级接口org.apache.kafka.clients.comsumer.internals.AbstractPartitionAssignor

b.按照消费者组进行轮训分配,

同个消费者组监听不同主题一样,把所有partition和comsumer列出来,订阅主题不一样导致分配不均

弊端:如果同一消费者组内,所订阅的消息是不相同的,在执行分区分配的时候不会轮训分配,可能导致分区分配不均匀

c.rangeAssignor默认策略,按照主题进行分配,如果不平均分配则第一个消费者会分配的比较多,一个消费者监听不同主题也不影响

弊端;对于一个topic 消费者多消耗一个分区影响不大

topic越多消费的分区也越多,则性能有所下降

平衡:如何均衡的将topic下的所有partition分配给消费者,从而使得消息的消费速度达到最快

rebalance重平衡 重新进行partition的分配,从而使得partition分配重新达到平衡状态

发生rebalance的条件:

1.当消费者组内的消费者数量发生变化,就会产生重新分配partition

2.分区的数量发生变化时

 

自动提交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只有收到分区内所有副本写入成功才会认为消息推送成功

leader会维持一个与其保持同步的replica集合,该集合就是ISR,leader副本也在isr里面

存在问题?

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同步数据

ACK保障生产者投递可靠性

partition多副本保障了消息存储的可靠性

hw:是所有副本中最小的leo,保证消费数据的一致性和副本数据的一致性

日志清理策略:

背景:数据持久化到磁盘上,为了控制磁盘容量,需要对过去的消息进行清理。

1.内部有个定时任务定期检查删除日志,默认是5分钟。

2.基于时间删除

每个日志段文件都维护一个最大时间戳,每次新写入消息时,都会更新该字段,一个segment日志段写满后,不再接收消息,最大时间戳字段保持不变。

kafka通过将当前时间与该最大时间戳进行比较,判断是否过期

3.基于大小超过阈值

超过阈值的部分必须大于一个日志段的大小。

如果阈值设置的为1000mb,那么超过阈值的部分就是(500+10)mb

大于日志块的大小,此时会删除最老的那部分日志段

4.日志压缩

log.cleanup.policy=compact启用压缩策略

按照消息key进行整理,相同key不同value只保留最后一个

利用Page cache

用于缓存文件的页数据,页是逻辑上的概念,因此page cache 是与文件系统同级的,作用是加速数据的IO,写数据首先写入缓存,将写入的页进行标记为dirty,

之后向外部存储flush,读数据的时候先读取缓存,没有再读取外部存储。

每一个文件都是一棵树,树的每个节点都是一个页,根据文件内的偏移量确定所在页

kafka高性能zerocopy(SendFile)

Kafka高性能从如下几个点答:

1.存储模型,topic多分区,每个分区多segment段

2.索引文件查找,分段和稀疏存储

3.磁盘顺序写入效率高

4.异步发送,batich缓冲区批量发送

5.页缓存(不是很理解)

6.零拷贝 kafka采用sendFile

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值