Kafka学习笔记(4)深入

4.1 Kafka工作流程

在这里插入图片描述

Kafka中的消息是以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic

topic是逻辑上的概念,而partition是物理上的概念,每个partition对应一个log文件,该log文件中存储的信息就是producer生产的数据,Producer生产的数据会被不断的追加到该log文件末尾,且每条数据都有自己的offset(偏移量),消费者组中的每个消费者,都会实时记录自己消费到那个offset(偏移量),以便出错恢复时,从上次的位置继续消费。

4.2 Kafka文件存储机制

在这里插入图片描述
由于生产者生产的消息会不断追加到log文件末尾,为防止log文件过大导致数据定位效率低下,Kafka采用了分片和索引机制,将每个partition分为多个segment,每个segment对应两个文件“xxx.index”及“xxx.log”文件,这些文件位于一个文件夹下,该文件夹的命名规则为topic名称+分区序号,indexlog文件以当前segment的第一条消息的offset命名。

.index”文件存储大量的索引信息,“.log”文件存储大量的数据,索引文件中的元数据指向对应数据文件中message的物理偏移地址。

4.3 生产者(Producer)

4.3.1 分区策略

1)分区的原因

  • 方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了
  • 可以提高并发,以partition为单位读写

2)分区的原则

我们需要将producer发送的数据封装成一个ProducerRecord对象

  • 指明partition的情况下,直接将指明的值直接作为partition
  • 没有指明partition值但存在key的情况下,将keyhash值与topicpartition数进行取余得到partition
  • 都不存在的情况下,第一次调用时随机生成一个整数,将这个值与topic可用的partition总数取余得到partition值,也就是常说的轮询算法。

4.3.2 数据可靠性保证

为保证producer发送的数据,能可靠的发送到指定的topictopic的每个partition收到producer发送的数据后,都需要向producer发送ack,如果peoducer收到ack,就会进行下一轮的发送,否则重新发送数据。
在这里插入图片描述
1)副本数据同步策略

  • 半数以上完成同步,发送ack
    • 优点:延迟低
    • 缺点:选举新的leader时,容忍n台节点的故障,需要2n+1个副本
  • 全部完成同步,发送ack
    • 优点:选举新的leader时,容忍n台节点的故障,需要n+1个副本
    • 缺点:延迟高

Kafka采用第二种同步方案:其原因如下

  • 同样为了容忍n台节点的故障,第二种需要的副本更少,而kafka的每个分区都会保存大量的数据,第一种就会造成大量的数据冗余
  • 网络延迟对kafka的影响较小,可以不考虑

2)ISR

leader维护了一个动态的in-sync replica set(ISR),意为和leader保持同步的follower集合,当ISR中的follower完成数据的同步之后,leader就会给follower发送ack,如果follower长时间未向leader同步数据,则该follower将被踢出isr,该时间阈值由replica.lag.time.max.ms参数设定,Leader发生故障之后,就会从ISR中选举新的Leader

3)ack应答机制

​ 对于某些不太重要的数据,对数据的可靠性要求不高,能容忍数据的少量丢失,所以没必要等ISR中的follower全部接收成功

​ 所以kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,用户可以选择以下配置:

acks参数配置说明:

	- 0:`producer`不等待`broker`的`ack`,这一操作提供了一个最低的延迟,`broker`一接收到还没写入磁盘就已经返回,当`broker`故障时有可能丢失数据。
	- 1:`producer`等待`broker`的`ack`,`partition`的`leader`落盘成功后返回`ack`,如果在`follower`同步成功之前`leader`故障,那么将会丢失数据。
	- all(-1):`producer`等待`broker`的`ack`,`partition`的`leader`和`follower`全部落盘成功后才返回`ack`,但是如果在`follower`同步完成后,`broker`发送`ack`之前,`leader`发生故障,那么会造成数据重复。

4)数据一致性

log文件中包含HWLEO属性

  • LEO:每个副本的最后一个offset
  • HW:所有副本中最小的LEOHW之前的数据才对Consumer可见

(1)follower故障:follower发生故障后会被踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW。并将log文件高于HW的部分截取掉,从HW开始向leader进行同步,等待followerLEO大于等于该PartitionHW,即follower追上leader之后,就可以重新加入ISR了。

(2)leader故障:leader发生故障之后,会从ISR中选出一个新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据。

4.3.3 Exactly Once语义

​ 当ack=all时可以保证producerserver之间不会丢失数据,即At Least Once语义,当ack=0时,可以保证消息只会发送一次,即At Most Once语义。

At Least Once可以保证数据不丢失,但是不能保证数据不重复,相对的,At Most Once可以保证数据不重复,但是无法确保数据不丢失,所以针对一些特殊的需求,kafka引入了一个重大特性:幂等性

​ 幂等性:指producer无论向server发送多少次重复数据,server都只会持久化一条,幂等性结合At Least Once语义就构成了Exactly Once语义

​ 即:Exactly Once = At Least Once + 幂等性

4.4 消费者(Consumer)

4.4.1 消费方式

​ 消费者采用pull(拉)模式从broker中读取数据

- `push`(推):此模式很难适应消费速率不同的消费者,因为消息发送速率是由`broker`决定的,它的目标是尽可能以最快速率传递消息,但这样容易造成消费者来不及处理消息,
- `pull`(拉):此模式可以适应消费速率不同的消费者,但是其不足之处是如果`kafka`没有数据,消费者可能会陷入循环中,一直返回空数据,针对此问题,`kafka`的消费者在消费数据时会传入一个时长参数timeout,如果没有数据可消费,消费者会等待一段时间在返回。

4.4.2 分区分配策略

​ 一个consumer group中包含多个consumer,一个topic有多个partition,所以必然会涉及到partiton的分配问题,即确定那个partition由哪个consumer来消费。

Kafka有两种分配策略,一是RoundRobin,一是Range

  • RoundRobin

    轮询策略,一个消费者组监听多个主题(topic),kafka会根据对象TopicAndPartition把所有主题的partition的哈希值进行排序,当作一个对象进行顺序的轮询,每个消费者依次消费消息。

  • Range(默认策略):

    范围策略:根据给定的范围值划分消费对应分区的消费者

4.4.3 offset的存储

offset的作用:由于consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置继续消费,所以consumer需要实时记录自己消费到那个offset,以便于故障恢复后继续消费。

Kafka 0.9版本之前,consumer默认将offset保存在Zookeeper中,从0.9版本开始,consumer默认将offset保存在kafka一个内置的topic中,该topic_consumer_offsets

1)修改配置文件:consumer.properties

#是否把内部topic的信息(例如offset)暴露给cosumer,如果设置为true,就只能通过订阅的方式来获取内部topic的数据
exclude.internal.topics=false

2)读取offset

#0.11.0.0之前版本
./kafka-console-consumer.sh --topic _consumer_offsets --zookeeper [your.zk.url]:2181 --formatter "kafka.coordinator.GroupMetadaManager\$offsetsMessageFormatter" --consumer.config config/consumer.properties --from-begining

#0.11.0.0之后版本
./kafka-console-consumer.sh --topic _consumer_offsets --zookeeper [your.zk.url]:2181 --formatter "kafka.coordinator.group.GroupMetadaManager\$offsetsMessageFormatter" --consumer.config config/consumer.properties --from-begining

4.4.4 消费者组案例

1)需求:测试同一个消费者组中的消费者,同一时间只能有一个消费者消费

2)案例实操:

- 修改配置文件设置groupId
cd /home/kafka/config
vi consumer.properties

#插入以下内容后保存退出
group.id=testGroup
  • 启动消费者组的消费者
#启动消费者,多启动几个
./kafka-xonsole-consumer.sh --zookeeper [your.zk.url]:2181 --topic first --consumer.config config/consumer.properties

./kafka-xonsole-consumer.sh --bootstrap-server [your.kafka.url]:9092 --topic first --consumer.config config/consumer.properties
  • 启动生产者
./kafka-console-producer.sh --broker-list [your.kafka.url]:9092 --topic first
  • 查看启动的消费者

同一时刻只有一个消费者接收到消息

4.5 高效读写&ZK的作用

高效读写数据

1)顺序写磁盘

Kafkaproducer生产数据,要写入到log文件中,写的过程是一直追加到文件的尾端,为顺序写,数据表明:顺序写优于随机写,因为顺序写节省了大量磁头寻址的时间

2)零复制\零拷贝技术
在这里插入图片描述

ZK的作用

Kafka集群中有一个broker会被选举为Controller,负责管理集群broker的上下线,所有的topic分区副本分配leader选举等工作,Controller的管理工作都是依赖于Zookeeper

4.6 事务

Kafka0.11版本开始引入了事务支持,事务可以保证KafkaExactly Once语义的基础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败。

Producer事务

​ 为了实现跨分区跨会话的事务,需要引入一个全局唯一的TransactionId,并将Producer获得的PIDTransactionID绑定,这样当Producer重启后就可以通过正在进行的TraansactionId获得原来的PID

​ 为了管理TransactionKafka引入了一个新的组件TCProducer就是通过和TC交互获得TransactionID对应的任务状态,TC还负责将事务所有写入Kafka的一个内部Topic,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行。

Consumer事务:

​ 由于Consumer可以通过offset访问任意信息,而且不同的SegmentFile生命周期不同,同一事务的消息可能会出现重启后被删除的情况。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序小达人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值