kafka深入研究之路(1)-剖析各原理02

kafka深入研究之路(1)-剖析各原理02

接着上一文的内容 继续升入研究

topic如何创建于删除的

topic的创建
kafka深入研究之路(1)-剖析各原理02

具体流程文字为:

1、 controller 在 ZooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被创建,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。
2、 controller从 /brokers/ids 读取当前所有可用的 broker 列表,对于 set_p 中的每一个 partition:
     2.1、 从分配给该 partition 的所有 replica(称为AR)中任选一个可用的 broker 作为新的 leader,并将AR设置为新的 ISR 
     2.2、 将新的 leader 和 ISR 写入 /brokers/topics/[topic]/partitions/[partition]/state 
3、 controller 通过 RPC 向相关的 broker 发送 LeaderAndISRRequest。

注意:此部分 和 partition 的leader选举过程很类似 都是需要 zk参与 相关信息都是记录到zk中
controller在这些过程中启到非常重要的作用。

topic的删除
kafka深入研究之路(1)-剖析各原理02

文字过程:

1、 controller 在 zooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被删除,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。 
2、 若 delete.topic.enable=false,结束;否则 controller 注册在 /admin/delete_topics 上的 watch 被 fire,controller 通过回调向对应的 broker 发送 StopReplicaRequest。

前面我们讲到的很多的处理故障过程 包括 topic创建删除 partition leader的转换 broker发生故障的过程中如何保证高可用 都涉及到了一个组件 controller,关于kafka中出现的相关概念名词,我会专门的写一个博客,这里先简单的提一下。
Controller:Kafka 集群中的其中一个服务器,用来进行 Leader Election 以及各种 Failover。

大家有没有想过一个问题,就是如果controller出现了故障,怎么办,如何failover的呢?我们往下看。

首先我们最一个实验,我们在zk中找到controller在哪个broker上,并查看controller_epoch的次数

[zk: localhost:2181(CONNECTED) 14] ls /kafkagroup/controller
controller_epoch   controller
[zk: localhost:2181(CONNECTED) 14] ls /kafkagroup/controller
[]
[zk: localhost:2181(CONNECTED) 15] get /kafkagroup/controller
{"version":1,"brokerid":1002,"timestamp":"1566648802297"}
[zk: localhost:2181(CONNECTED) 22] get /kafkagroup/controller_epoch
23

我们可以看到当前的controller在1002上 在此之前发了23次controller的切换

我们手动到 1002节点上杀死kafka进程
[hadoop@kafka02-55-12$ jps
11665 Jps
10952 Kafka
11068 ZooKeeperMain
10495 QuorumPeerMain
[hadoop@kafka02-55-12$ kill -9 10952
[hadoop@kafka02-55-12$ jps
11068 ZooKeeperMain
11678 Jps
10495 QuorumPeerMain

再看zk上的信息,相关信息已经同步到zk中了

[zk: localhost:2181(CONNECTED) 16] get /kafkagroup/controller
{"version":1,"brokerid":1003,"timestamp":"1566665835022"}
[zk: localhost:2181(CONNECTED) 22] get /kafkagroup/controller_epoch
24
[zk: localhost:2181(CONNECTED) 25] ls /kafkagroup/brokers
[ids, topics, seqid]
[zk: localhost:2181(CONNECTED) 26] ls /kafkagroup/brokers/ids
[1003, 1001]

在后台日志中就会看到很多
[hadoop@kafka03-55-13 logs]$ vim state-change.log
[2019-08-25 01:01:07,886] TRACE [Controller id=1003 epoch=24] Received response {error_code=0} for request UPDATE_METADATA wit
h correlation id 7 sent to broker 10.211.55.13:9092 (id: 1003 rack: null) (state.change.logger)
[hadoop@kafka03-55-13 logs]$ pwd
/data/kafka/kafka-server-logs/logs
state改变的信息

[hadoop@kafka03-55-13 logs]$ tailf controller.log
[2019-08-25 01:05:42,295] TRACE [Controller id=1003] Leader imbalance ratio for broker 1002 is 1.0 (kafka.controller.KafkaCont
roller)
[2019-08-25 01:05:42,295] INFO [Controller id=1003] Starting preferred replica leader election for partitions (kafka.controll
er.KafkaController)

接下来,我们具体的分析一下,他到底内部发生了什么,如何切换的
当 controller 宕机时会触发 controller failover。每个 broker 都会在 zookeeper 的 "/controller" 节点注册 watcher,当 controller 宕机时 zookeeper 中的临时节点消失,所有存活的 broker 收到 fire 的通知,每个 broker 都尝试创建新的 controller path,只有一个竞选成功并当选为 controller。

当新的 controller 当选时,会触发 KafkaController.onControllerFailover 方法,在该方法中完成如下操作:

1、 读取并增加 Controller Epoch。
2、 在 reassignedPartitions Patch(/admin/reassign_partitions) 上注册 watcher。
3、 在 preferredReplicaElection Path(/admin/preferred_replica_election) 上注册 watcher。
4、 通过 partitionStateMachine 在 broker Topics Patch(/brokers/topics) 上注册 watcher。
5、 若 delete.topic.enable=true(默认值是 false),则 partitionStateMachine 在 Delete Topic Patch(/admin/delete_topics) 上注册 watcher。
6、 通过 replicaStateMachine在 Broker Ids Patch(/brokers/ids)上注册Watch。
7、 初始化 ControllerContext 对象,设置当前所有 topic,“活”着的 broker 列表,所有 partition 的 leader 及 ISR等。
8、 启动 replicaStateMachine 和 partitionStateMachine。
9、 将 brokerState 状态设置为 RunningAsController。
10、 将每个 partition 的 Leadership 信息发送给所有“活”着的 broker。
11、 若 auto.leader.rebalance.enable=true(默认值是true),则启动 partition-rebalance 线程。
12、 若 delete.topic.enable=true 且Delete Topic Patch(/admin/delete_topics)中有值,则删除相应的Topic。

可以看到,都是在zk上进行交互,controller的从新选举会依次通知 zk中相关的位置 并注册watcher ,在此过程中 就会发送 partition的leader的选举,还会发生partition-rebalanced 删除无用的topic等一系列操作(因为我们这里是直接考虑的最糟糕的情况就是broker宕机了一个,然而宕机的这台上就是controller)


consumer是如何消费消息的

重要概念:每个 Consumer 都划归到一个逻辑 Consumer Group 中,一个 Partition 只能被同一个 Consumer Group 中的一个 Consumer 消费,但可以被不同的 Consumer Group 消费。

若 Topic 的 Partition 数量为 p,Consumer Group 中订阅此 Topic 的 Consumer 数量为 c, 则:
p < c: 会有 c - p 个 consumer闲置,造成浪费
p > c: 一个 consumer 对应多个 partition
p = c: 一个 consumer 对应一个 partition
应该合理分配 Consumer 和 Partition 的数量,避免造成资源倾斜,
本人建议最好 Partiton 数目是 Consumer 数目的整数倍。

在consumer消费的过程中如何把partition分配给consumer?
也可以理解为consumer发生rebalance的过程是如何的?
生产过程中 Broker 要分配 Partition,消费过程这里,也要分配 Partition 给消费者。

类似 Broker 中选了一个 Controller 出来,消费也要从 Broker 中选一个 Coordinator,用于分配 Partition。// Coordinator 和 Controller 都是一个概念,协调者 组织者

当 Partition 或 Consumer 数量发生变化时,比如增加 Consumer,减少 Consumer(主动或被动),增加 Partition,都会进行 consumer的Rebalance。//发生rebalance发生在consumer端

见图:
kafka深入研究之路(1)-剖析各原理02

文字信息为:
1、Consumer 给 Coordinator 发送 JoinGroupRequest 请求。这时其他 Consumer 发 Heartbeat 请求过来时,Coordinator 会告诉他们,要 Rebalance了。其他 Consumer 也发送 JoinGroupRequest 请求。
2、Coordinator 在 Consumer 中选出一个 Leader,其他作为 Follower,通知给各个 Consumer,对于 Leader,还会把 Follower 的 Metadata 带给它。
3、Consumer Leader 根据 Consumer Metadata 重新分配 Partition。
4、Consumer 向 Coordinator 发送 SyncGroupRequest,其中 Leader 的 SyncGroupRequest 会包含分配的情况。
5、Coordinator 回包,把分配的情况告诉 Consumer,包括 Leader。

小结:
消费组与分区重平衡
可以看到,当新的消费者加入消费组,它会消费一个或多个分区,而这些分区之前是由其他消费者负责的;另外,当消费者离开消费组(比如重启、宕机等)时,它所消费的分区会分配给其他分区。这种现象称为重平衡(rebalance)。
重平衡是 Kafka 一个很重要的性质,这个性质保证了高可用和水平扩展。
不过也需要注意到,在重平衡期间,所有消费者都不能消费消息,因此会造成整个消费组短暂的不可用。而且,将分区进行重平衡也会导致原来的消费者状态过期,从而导致消费者需要重新更新状态,这段期间也会降低消费性能。

文字过程实例:
消费者通过定期发送心跳(hearbeat)到一个作为组协调者(group coordinator)的 broker 来保持在消费组内存活。这个 broker 不是固定的,每个消费组都可能不同。当消费者拉取消息或者提交时,便会发送心跳。
如果消费者超过一定时间没有发送心跳,那么它的会话(session)就会过期,组协调者会认为该消费者已经宕机,然后触发重平衡。可以看到,从消费者宕机到会话过期是有一定时间的,这段时间内该消费者的分区都不能进行消息消费;通常情况下,我们可以进行优雅关闭,这样消费者会发送离开的消息到组协调者,这样组协调者可以立即进行重平衡而不需要等待会话过期。
在 0.10.1 版本,Kafka 对心跳机制进行了修改,将发送心跳与拉取消息进行分离,这样使得发送心跳的频率不受拉取的频率影响。另外更高版本的 Kafka 支持配置一个消费者多长时间不拉取消息但仍然保持存活,这个配置可以避免活锁(livelock)。活锁,是指应用没有故障但是由于某些原因不能进一步消费。

接下来思考一个问题,consumer是如何取消息的 Consumer Fetch Message
Consumer 采用"拉模式"消费消息,这样 Consumer 可以自行决定消费的行为。
Consumer 调用 Poll(duration)从服务器拉取消息。拉取消息的具体行为由下面的配置项决定:

#consumer.properties
#消费者最多 poll 多少个 record
max.poll.records=500
#消费者 poll 时 partition 返回的最大数据量
max.partition.fetch.bytes=1048576
#Consumer 最大 poll 间隔
#超过此值服务器会认为此 consumer failed 
#并将此 consumer 踢出对应的 consumer group 
max.poll.interval.ms=300000

小结:
1、在 Partition 中,每个消息都有一个 Offset。新消息会被写到 Partition 末尾(最新的一个 Segment 文件末尾), 每个 Partition 上的消息是顺序消费的,不同的 Partition 之间消息的消费顺序是不确定的。
2、若一个 Consumer 消费多个 Partition, 则各个 Partition 之前消费顺序是不确定的,但在每个 Partition 上是顺序消费。
3、若来自不同 Consumer Group 的多个 Consumer 消费同一个 Partition,则各个 Consumer 之间的消费互不影响,每个 Consumer 都会有自己的 Offset。

举个官方小栗子:
kafka深入研究之路(1)-剖析各原理02


Offset 如何保存?
Consumer 消费 Partition 时,需要保存 Offset 记录当前消费位置。

Offset 可以选择自动提交或调用 Consumer 的 commitSync() 或 commitAsync() 手动提交,相关配置为:

#是否自动提交 offset
enable.auto.commit=true
#自动提交间隔。enable.auto.commit=true 时有效
auto.commit.interval.ms=5000
//enable.auto.commit 的默认值是 true;就是默认采用自动提交的机制。
auto.commit.interval.ms 的默认值是 5000,单位是毫秒。5 秒

Offset 保存在名叫 __consumeroffsets 的 Topic 中。写消息的 Key 由 GroupId、Topic、Partition 组成,Value 是 Offset。

一般情况下,每个 Key 的 Offset 都是缓存在内存中,查询的时候不用遍历 Partition,如果没有缓存,第一次就会遍历 Partition 建立缓存,然后查询返回

__consumeroffsets 的 Partition 数量由下面的 Server 配置决定:

offsets.topic.num.partitions=50

默然的consumeroffsets是没有repale副本的 需要我们通过在一开始的参数指定,或者通过后期的增加 consumeroffsets 的副本json的方式动态添加

auto.create.topics.enable=true      
default.replication.factor=2
num.partitions=3

经过测试上面的3个参数虽然在搭建好kafak的时候第一次指定了,但是 consumeroffsets副本数还是1个,这个的关键在于,配置文件中需要指定
kafka配置文件关于此参数解释如下:
############################# Internal Topic Settings ############################# 内部主题设置
#组元数据内部主题“
consumer_offsets”和“transaction_state”的复制因子
#对于除开发测试之外的任何其他内容,建议使用大于1的值以确保可用性,例如设置成3。
The replication factor for the group metadata internal topics "__consumer_offsets" and "
transaction_state"
For anything other than development testing, a value greater than 1 is recommended for to ensure availability such as 3.

offsets.topic.replication.factor=2
transaction.state.log.replication.factor=2
transaction.state.log.min.isr=2
//关于这3个参数,可以在修改kafka程序中指定的 consumer_offsets 的副本数
然后@上海-马吉辉 说只要num.partitions=3,__consumer_offsets副本数就是3,我测试不是 还是1
所以还是以offsets.topic.replication.factor参数控制为准
如果不是第一次启动kafka 那几个配置只有在初次启动生效的。 apache kafka 下载下来应该都默认是 1 吧,2.* 也是 1 啊。
可以这样修改
先停止kafka集群,删除每个broker data目录下所有
consumeroffsets*
然后删除zookeeper下rmr /kafkatest/brokers/topics/consumer_offsets 然后重启kafka
消费一下,这个__consumer_offsets就会创建了
注意:是在第一次消费时,才创建这个topic的,不是broker集群启动就创建,还有那个
trancation_state topic也是第一次使用事务的时候才会创建

小结:在生产上,没人去删zk里的内容,危险系数大,还是推荐动态扩副本,只要把json写对就好
控制 __consumer_offsets 的副本数 的关键参数为这3个。


Offset 保存在哪个分区上,即 __consumeroffsets 的分区机制,可以表示为
groupId.hashCode() mode groupMetadataTopicPartitionCount
groupMetadataTopicPartitionCount 是上面配置的分区数。因为一个 Partition 只能被同一个 Consumer Group 的一个 Consumer 消费,因此可以用 GroupId 表示此 Consumer 消费 Offeset 所在分区。

Kafka 中的可靠性保证有如下四点:

1、对于一个分区来说,它的消息是有序的。如果一个生产者向一个分区先写入消息A,然后写入消息B,那么消费者会先读取消息A再读取消息B。
2、当消息写入所有in-sync状态的副本后,消息才会认为已提交(committed)。这里的写入有可能只是写入到文件系统的缓存,不一定刷新到磁盘。生产者可以等待不同时机的确认,比如等待分区主副本写入即返回,后者等待所有in-sync状态副本写入才返回。
3、一旦消息已提交,那么只要有一个副本存活,数据不会丢失。
4、消费者只能读取到已提交的消息。

看到这里,我们对kafka有了全新的认识 ,kafka到底为什么这么厉害,下面总结了11点
1、批量处理
2、客户端优化
3、日志格式优化
4、日志编码
5、消息压缩
6、建立索引
7、分区
8、一致性
9、顺序写盘
10、页缓存 *
11、零拷贝


有关内存映射:
即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。 Memory Mapped Files(后面简称mmap)也被翻译成内存映射文件,它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。 通过mmap,进程像读写硬盘一样读写内存,也不必关心内存的大小有虚拟内存为我们兜底。 mmap其实是Linux中的一个用来实现内存映射的函数,在Java NIO中可用MappedByteBuffer来实现内存映射。

Kafka消息压缩
生产者发送压缩消息,是把多个消息批量发送,把多个消息压缩成一个wrapped message来发送。和普通的消息一样,在磁盘上的数据和从producer发送来到broker的数据格式一模一样,发送给consumer的数据也是同样的格式。



参考链接Wie:
Kafka学习之路 (三)Kafka的高可用 https://www.cnblogs.com/qingyunzong/p/9004703.html
理解Kafka消费者属性的enable.auto.commit https://blog.csdn.net/chaiyu2002/article/details/89472416
Kafka为了追求极致的性能,有这11大牛逼之处 https://www.toutiao.com/i6716428216233361931/
图解Kafka的零拷贝技术到底有多牛?
https://mp.weixin.qq.com/s?__biz=MzA5MzQ2NTY0OA==&mid=2650798164&idx=1&sn=9715585f301aabd7e0e7f553bb10d479&chksm=8856250bbf21ac1d03728214bb7aa5ccccf2946372bb6f3ada8bade36b5e3f37ad5a4fd0ba11&mpshare=1&scene=1&srcid=&key=b31ff5fcc4dff71035f05512e3aa86195679985db03602e4308e89af3fd9504575d6f0af34b4ce67afdba4bf09c114daadee0ce484c0be2e225f44aa4eb69f2dde805cc8b66dc56c11542396ae6cd5cf&ascene=1&uin=MTE3MjA4OTEyMQ%3D%3D&devicetype=Windows+10&version=62060739&lang=zh_CN&pass_ticket=7Zi3lF9%2F88fCclSxasjE0u%2F%2FBIjdqJsRxIIe1l6jAPvw%2B2D2lJ%2BNbSfXgnayP0D0
图解Kafka消息是被怎么存储的?
https://mp.weixin.qq.com/s?__biz=MzA5MzQ2NTY0OA==&mid=2650798146&idx=1&sn=0c9fcf489a6b3d479a12718e36205012&chksm=8856251dbf21ac0b721a1cba441af07f258cc834f8c0d5b5adc6feaf54d0cdc5683c22fa72ce&mpshare=1&scene=1&srcid=0321y7pAUNnwkOkt6C5Xnl9M&key=cb09f7b1396893c75895655d118c8084827fff6e6825375876d7fd781d8912612d4add3171c6e39e1d9761e5947cd389765cc5a783f79ef97f8c4e97a8d27779763c8776f858823ee0f908bbcae9e748&ascene=1&uin=MTE3MjA4OTEyMQ%3D%3D&devicetype=Windows+10&version=62060730&lang=zh_CN&pass_ticket=EV41Y0Ytgsx7ziFTeIvv67NJykH0GUa%2FzgbiQzYEnpi63r9S6yW1r%2Bznb%2FyhkGgK

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《深入理解kafka(核心设计与实践原理) pdf》是一本介绍了Kafka技术原理、实现和部署的全面指南。它从多个角度阐述了Kafka的核心设计思想和实践原理,让读者可以更深入地理解Kafka的工作机制和应用场景。 本书首先介绍了Kafka的基本概念和架构,包括生产者、消费者、Broker、Topic和Partition等。随着阅读的深入,读者将学会如何使用Kafka进行数据传输和存储,并了解到Kafka如何支持高吞吐量、高可用性和高扩展性。 《深入理解kafka(核心设计与实践原理) pdf》还重点阐述了Kafka的持久化存储机制、消息传递方式和消息压缩技术。它详细介绍了Kafka中不同的数据结构和算法,以及如何优化Kafka的性能和可靠性。 此外,本书还附带了丰富的实例和案例分析,帮助读者更深入地了解Kafka的应用场景和实际应用。例如,它介绍了如何使用Kafka进行日志集中存储、实时流式处理、事件驱动等。 总之,《深入理解kafka(核心设计与实践原理) pdf》是一本深度剖析Kafka技术的书籍,不仅适合Kafka初学者,也适合已经有一定经验的开发者和架构师。它不仅告诉读者Kafka的基本原理,更重要的是让读者深入理解Kafka的应用场景,掌握Kafka的最佳实践。 ### 回答2: 《深入理解kafka(核心设计与实践原理) pdf》是一本对于Kafka消息队列系统进行深入探究的书籍。Kafka是开源的分布式消息系统,它具有高吞吐、可靠性和可扩展性等优点,因此已经被广泛应用于各类实时数据处理场景中。 该书从Kafka的基础概念讲起,包括Kafka的消息模型、生产者和消费者的架构以及Kafka集群的工作原理。它还详细介绍了Kafka的API,包括生产者API、消费者API和管理API等,并结合实际案例进行讲解,使读者能够更好地理解这些API的使用方法和场景。 书中还介绍了Kafka的重要性能指标,包括吞吐量、延迟和可靠性等指标,并提供了一些优化性能的实践方法,帮助读者更好地提高Kafka的应用性能。 此外,该书还深入研究Kafka如何处理故障和容错,包括故障转移、数据备份和恢复等方面。它也讨论了一些高级主题,如Kafka的安全性、复制和分区等,并提供了一些实践案例和代码示例,以帮助读者更好地掌握这些概念和技术。 总而言之,《深入理解kafka(核心设计与实践原理) pdf》是一本权威的Kafka技术指南,它通过清晰地阐述Kafka的基本原理、性能指标、容错处理和高级主题等内容,全面介绍了Kafka的核心设计和实践原理,帮助读者更好地应用Kafka来处理实时数据和构建可靠的分布式系统。 ### 回答3: 《深入理解kafka(核心设计与实践原理) pdf》是kafka技术方面的一本经典书籍,该书着重介绍了kafka的核心设计和实践原理kafka是一种高吞吐量分布式消息系统,它能够快速的处理流式数据,因此在实时处理大数据方面非常有用。 该书主要分为四部分,第一部分介绍了kafka的基础知识,包括kafka是什么,为什么要使用kafka等,还详细介绍了kafka的架构、核心组件和通信协议等。第二部分介绍了kafka的生产者和消费者模型,包括kafka的消息模型、消息处理流程等。第三部分深入讲解了kafka集群的管理和优化,包括kafka的监控、故障排查、性能调优等。最后一部分介绍了kafka的高级应用,包括kafka在大数据处理、实时数据分析等方面的应用。 该书通俗易懂,以实例为主,将复杂的技术原理浓缩到了1000多页的书籍里,给读者提供很好的阅读体验。在这本书中,读者可以深入理解kafka的设计思想,掌握kafka的核心原理和实践技巧,能够高效地应用kafka在实际项目中。无论你是kafka的初学者还是熟练使用者,本书都是一本非常优秀的参考书籍,有助于你更深入理解kafka的技术实现细节。如果你对kafka感兴趣,想要深入理解kafka的设计和工作原理,这本书将是你的不二之选。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值