Kafka高性能探究

常见的消息队列

常见的消息队列主要有RabbitMQ,RocketMQ,ActiveMQ,Kafka,ZeroMQ等等。所有的消息队列都有共同的特征:解耦,晓峰。
今天我们主要说说Kafka(Kafka 是消息引擎系统,也是一个分布式流处理平台)。

Kafka特征

Kafka:高性能跨语言分布式发布订阅模式,高吞吐率,持久化,完全分布式,支持在线流处理,离线批理。

Kafka逻辑结构图

image.png

Kafka流程图

image.png

高性能特征

1. 生产者
生产者分区

分区的作用就是提供负载均衡的能力,另一个作用是为了实现系统的高伸缩性。不同的分区能够被放置到不同节点的机器上,而数据的读写操作也都是针对分区这个粒度而进行的,这样每个节点的机器都能独立地执行各自分区的读写请求处理。
分区策略:API中指出我们可以指定分区,不指定的话就是按照key 的取余主题的分区数。如果既没有分区数又没有key,则随机生成一个随机数然后轮训。
轮询策略:也称 Round-robin 策略,即顺序分配。


image.png

随机策略:也称 Randomness 策略。所谓随机就是我们随意地将消息放置到任意一个分区上。


image.png

按消息键保序策略:一旦消息被定义了 Key,那么你就可以保证同一个 Key 的所有消息都进入到相同的分区里面,由于每个分区下的消息处理都是有顺序的,故这个策略被称为按消息键保序策略。
image.png
副本(冗余数据,备份)
image.png

第一,在 Kafka 中,副本分成两类:领导者副本(Leader Replica)和追随者副本(Follower Replica)。每个分区在创建时都要选举一个副本,称为领导者副本,其余的副本自动称为追随者副本。
第二,追随者副本是不对外提供服务,任务就是从领导者副本异步拉取消息,并写入到自己的提交日志中,从而实现与领导者副本的同步。
第三,当领导者副本挂掉了,Kafka 依托于 ZooKeeper 提供的监控功能能够实时感知到,并立即开启新一轮的领导者选举,从追随者副本中选一个作为新的领导者。老 Leader 副本重启回来后,只能作为追随者副本加入到集群中。
这个设计保证了数据的读一致性问题。
全部flower收到消息在ACK,延迟高,n台故障n+1个副本。(一台服务挂掉,永远就不会ACK了。ISR机制克服了这种情况)

Kafka Broker 久化数据。Kafka 使用消息日志(Log)来保存数据,一个日志就是磁盘上一个只能追加写消息的物理文件。因为只能追加写入,故避免了缓慢的随机 I/O 操作,改为性能较好的顺序 I/O 写操作,这也是实现 Kafka 高吞吐量特性的一个重要手段。Kafka是通过日志段(Log Segment)机制。在 Kafka 底层,一个日志又近一步细分成多个日志段,消息被追加写到当前最新的日志段中,当写满了一个日志段后,Kafka 会自动切分出一个新的日志段,并将老的日志段封存起来。Kafka 在后台还有定时任务会定期地检查老的日志段是否能够被删除,从而实现回收磁盘空间的目的。


image.png

Kafka的高吞吐量处理流程


image.png

Kafka 的 Broker 端有个 SocketServer 组件(请求分发器),它也有对应的 Acceptor 线程和一个网络线程池(工作线程池)。Kafka 提供了 Broker 端参数 num.network.threads设置网络线程池的线程数。其默认值是 3。

Acceptor 线程采用轮询的方式将入站请求公平地发到所有网络线程中。


image.png

当网络线程拿到请求后,它不是自己处理,而是将请求放入到一个共享请求队列中。Broker 端还有个 IO 线程池,负责从该队列中取出请求,执行真正的处理。如果是 PRODUCE 生产请求,则将消息写入到底层的磁盘日志中;如果是 FETCH 请求,则从磁盘或页缓存中读取消息。

Broker 端参数num.io.threads控制了这个线程池中的线程数。目前该参数默认值是 8,表示每台 Broker 启动后自动创建 8 个 IO 线程处理请求。
Purgatory 的组件,它是用来缓存延时请求的。就是那些一时未满足条件不能立刻处理的请求。比如设置了 acks=all 的 PRODUCE 请求,一旦设置了 acks=all,那么该请求就必须等待 ISR 中所有副本都接收了消息后才能返回,此时处理该请求的 IO 线程就必须等待其他 Broker 的写入结果。当请求不能立刻处理时,它就会暂存在 Purgatory 中。稍后一旦满足了完成条件,IO 线程会继续处理该请求,并将 Response 放入对应网络线程的响应队列中。

消费者:

Consumer Group 是且具有容错性的消费者机制。这个消费者组里面有多个消费者或消费者实例,它们共享一个公共的 Group ID。组内的所有消费者协调在一起来消费订阅主题的分区。

Offset 其实对于 Consumer Group 而言,它是Map结构,Key 是分区(Group ID,主题名,分区号),V 对应 Consumer 消费该分区的最新位移。老版本的 Consumer Group 把位移保存在 ZooKeeper 中。 ZooKeeper 这类元框架其实并不适合进行频繁的写更新,而 Consumer Group 的位移更新却是一个非常频繁的操作。在新版本的 Consumer Group 中,Kafka 社区重新设计了 Consumer Group 的位移管理方式,采用了将位移保存在 Kafka 内部主题的方法。新版本的 Consumer Group 将位移保存在 Broker 端的内部主题中。

Rebalance 就是让一个 Consumer Group 下所有的 Consumer 实例就如何消费订阅主题的所有分区达成共识的过程。在 Rebalance 过程中,所有 Consumer 实例共同参与,在协调者组者(Coordinator:位移管理和组成员管理)的帮助下,完成订阅主题分区的分配。(stop the word)

Coordinator:是通过groupID的hashCode值%(位移主题的分区默认50)副本所在在Broker就是Coordinator的存放位置。

重平衡:通知机制正是通过心跳线程来完成的。当协调者决定开启新一轮重平衡后,它会将“REBALANCE_IN_PROGRESS”封装进心跳请求的响应中,发还给消费者实例。

消费端的重平衡流程:

   加入组和等待领导者消费者分配方案。对应的是JoinGroup 请求和 SyncGroup 请求。

当组内成员加入组时,它会向协调者发送 JoinGroup 请求。在该请求中,每个成员都要将自己订阅的主题上报,这样协调者就能收集到所有成员的订阅信息。一旦收集了全部成员的 JoinGroup 请求后,协调者会从这些成员中选择一个担任这个消费者组的领导者。通常情况下,第一个发送 JoinGroup 请求的成员自动成为领导者。


image.png

image.png

image.png

image.png

image.png

你可能感兴趣的:(Kafka高性能探究)