Kafka 入门知识学习

1.Kafka基础概念

1.1 出世背景
Kafka是一个消息系统,是LinkedIn公司开发并开源出来的组件。Kafka原本用作LinkedIn的活动流(Activity Stream)和运营数据处理管道(Pipeline)的基础。 现在它已被多家公司作为多种类型的数据管道和消息系统使用。歪果仁就喜欢整一些看不懂的词汇,比如活动流,比如运营数据,就不能好好说话么。
活动流是啥?简单理解, 就是用户使用网站或者系统时产生的数据流,比如点击一个页面,查看一个图片,翻看一网页,搜索一个关键字,网站运营者需要对用户的这些行为进行统计,形成报表。

运营数据是啥? 就是计算机产生的监控日志信息,如CPU数据,IO数据等, 这些数据都是动态生成的,Linkedln这样的大公司,运营数据量非常大,通常的方式是生成这些数据,写入到log文件中,然后进行统计。活动流数据和运营数据对网站和软件产品非常重要,举几个栗子
1)动态汇总,将用户的信息动态汇总,或者自己监控,或者发给用户的朋友圈
2) 安全,实时监控用户访问信息,防止网络爬虫或者用户扩散垃圾信息,对API使用速率进行实时监控和控制,切断网站某些不正常活动。
3)机器硬件实时监控:对机器运行效率实时监控,对异常情况自动触发告警。
4)报表和批处理:将数据导入Hadoop平台,进行离线报表分析。
LinkedIn处理的时候就碰到几个问题:
1)日志量大,每天要处理10亿多条数据。
2)高吞吐量。
3)实时性能差。
现有的消息队列系统(messaging and queuing system)却很适合于在实时或近实时(near-real-time)的情况下使用,但它们对很长的未被处理的消息队列的处理很不给力,往往并不将数据持久化作为首要的事情考虑。这样就会造成一种情况,就是当把大量数据传送给Hadoop这样的离线系统后,这些离线系统每个小时或每天仅能处理掉部分源数据。 Kafka的目的就是要成为一个队列平台,仅仅使用它就能够既支持离线又支持在线使用这两种情况。

1.2 基本架构和原理
1.2.1.前置知识

消息队列
为什么要引入消息队列?举个例子,假如A发送消息给B,如果B在线,那么可以很顺利的通讯发消息,那如果B不在线,那就比较麻烦了,消息队列技术可以很好的解决这个问题。

消息队列技术是分布式应用间交换信息的一种技术,是两个系统通讯的桥梁和媒介,将两个系统解耦,不需要知道对方的位置和信息。 通过消息队列技术2个异构的系统可以进行通讯,尤其是大型系统。 消息队列可以保存在磁盘或者内存中。

消息队列技术底层都是socket通讯,socket在很多地方有用到,比如数据库,进程间通讯,jdbc等等底层都是socket通讯。

JMS是消息服务的规范,很多消息中间件技术都遵循JMS规范。
消息队列通讯模式
1)点对点通讯:点对点方式是最为传统和常见的通讯方式,它支持一对一、一对多、多对多、多对一等多种配置方式,支持树状、网状等多种拓扑结构。用人话描述一遍:就是一个人放东西,一个人取东西,这就是点对点。
2)发布/订阅 (Publish/Subscribe) 模式:发布/订阅功能使消息的分发可以突破目的队列地理指向的限制,使消息按照特定的主题甚至内容进行分发,用户或应用程序可以根据主题或内容接收到所需要的消息。发布/订阅功能使得发送者和接收者之间的耦合关系变得更为松散,发送者不必关心接收者的目的地址,而接收者也不必关心消息的发送地址, 而只是根据消息的主题进行消息的收发。发布/订阅 模式:就跟贴寻人启事,公告一样的道理,消息往公告上一贴,关心的人就去看看发生什么事,不关心的就当作一堆废纸,不用搭理。
Kafka很厉害,kafka将这两个概念整合到一起,他只有主题模式,但是能实现队列模式的效果,实现方式就是消费者组的引入:
消费者组:将一个或者多个消费者划到一起,取一个名标记,这就是消费者组,对于一个消费者组,处在同一个消费者组的消费者,只能有一个消费者消费。
发布订阅模式: 每个消费者组,只有一个消费者,那就是发布订阅,每个消费者都有自己的组。

每个组都能消费,那就是发布订阅模式。
队列模式:所有的消费者都在一个组里面。
消息队列特点
·数据缓冲作用
·降低耦合
·异构系统高效交互
Kafka是一个消息队列组件,它遵循JMS规范,基本工作流程, 生产者生产数据 -> kafka集群中转数据->消费者消费数据


1.2.2.架构和原理


生产者生产消息,将消息发送给Kafka集群, Kafka内在是分布式的,一个Kafka集群通常包括多个代理。为了均衡负载,将话题分成多个分区,每个代理存储一或多个分区。消费者从kafka主题中获取消息。多个生产者和消费者能够同时生产和获取消息。
1.Producer根据指定partition方法(round-robin、hash等),将消息发布到指定topic的partition里面
2.kafka集群接收到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),而不关注消息是否被消费。
3.Consumer从kafka集群pull数据,并控制获取消息的offset

1.2.3.基本概念
Broker:Kafka 集群包含一个或多个服务器,这种服务器被称为 broker。
Topic:每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic。(物理上不同 Topic 的消息分开存储,逻辑上一个 Topic 的消息虽然保存于一个或多个 broker 上, 但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处)。
Partition:Partition 是物理上的概念,每个 Topic 包含一个或多个 Partition。
Producer:负责发布消息到 Kafka broker。
Consumer:消息消费者,向 Kafka broker 读取消息的客户端。
Consumer Group:每个 Consumer 属于一个特定的 Consumer Group(可为每个 Consumer 指定 group name,若不指定 group name 则属于默认的 group)。

1.2.4.Kafka特点
1)分布式流平台,支持消息的分区(mr的分区类似),支持多个服务器之间消息分区
2)支持发布和订阅数据流,类似于消息系统
3)支持分布式和副本集群方式,来存储数据流
4)实时处理数据流
5) 支持多种源数据,数据库交互、app双向交互
6)水平可伸缩
7) 容错好
8)速度快
9)多种方式存储,持久化存储内存,磁盘秒级
10)海量数据,TB级高吞吐量:支持每秒百万消息,廉价硬件
11)多客户端支持,很容易集成不同平台,java,python,和多源进行协同,它是一个
12)中间件的基因,跨平台和跨语言,开源

2.Kafka初体验
2.1环境准备

1)kafka下载
kafka2.1.2官网下载: https://www.apache.org/dyn/closer.cgi?path=/kafka/0.10.2.1/kafka_2.12-0.10.2.1.tgz
2) zookeeper下载
zookeeper3.3.6官网地址: http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.3.6/zookeeper-3.3.6.tar.gz
3) JDK下载
kafka和zookeeper前提是安装好了jdk,注意你电脑是32位还是64为
jdk官网下载地址: http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
4)关闭防火墙
否则zk启动会报错no route tohost
· 查看防火墙状态,使用root账号执行
service iptables status
·关闭防火墙
service iptables stop
·查看防火墙开机启动状态
chkconfig iptables --list
·关闭防火墙开机启动
chkconfig iptables off
5)配置好host

2.2 Kafka小试牛刀
2.2.1 单个broker初体验
1.安装单节点的kafka
下载下来了之后直接解压就可以运行单节点的Kafka,因为Kafka需要用zookeeper做高可用,如果没有安装zk,也没有关系,使用它自带的配置启动就可以。
1)启动自带配置的zk
启动zk命令:  bin/zookeeper-server-start.sh config/zookeeper.properties

2)启动kafka
kafka启动:bin/kafka-server.start.sh config/server.properites
kafka启动成功

3)创建一个topic
创建topic: bin/kafka-topics.sh --create --zookeeper kafka01:2181 --replication-factor 1 --partitions 1 --topic test
查看topic: bin/kafka-topicts.sh --list --zookeeper kafka01:2181
4)启动生产者
命令: bin/kafka-console-producer.sh --broker-list kafka:9092 --topic test
启动之后,输入2行

5)启动消费者
命令: bin/kafka-console-consumer.sh --zookeeper kafka01:9202 --topic test --from-beginning
消费者接收到2行消息

总结
1.启动zk
命令: bin/zookeeper-server-start.sh config/zookeeper.properties
2.启动kafka
命令:bin/kafka-server.start.sh config/server.properites
参数:指定kafka的配置文件
3.创建主题
命令:bin/kafka-topics.sh --create --zookeeper kafka01:2181 --replication-factor 1 --partitions 1 --topic test
参数:
1)create:指定创建动作;
2)zookeeper:指定zookeeper客户端;
3)replication-factor:指定主题副本个数;
4)partitions:指定分区个数;
5)topic:指定主题名称;

查看topic: bin/kafka-topicts.sh --list --zookeeper kafka01:2181
4.启动生产者
命令:bin/kafka-console-producer.sh --broker-list kafka01:9092 --topic test
参数:
1)broker-list:指定broker;
2)topic:指定主题名,从参数可以看出来, 生产者是不直接和zk交互的
5.启动消费者
命令:bin/kafka-console-consumer.sh --zookeeper kafka01:2181 --topic test --from-beginning
参数:
1)zookeeper:指定zookeeper客户端;
2)topic:指定主题名;
3)from-beginning:从topic头开始读取消息;

2.2.2 多个broker初体验
前面已经配置了一个单节点kafka服务,再次扩展演示kafka集群多节点可用性、容错性,也为kafka分布式集群做好铺垫。
1)配置kafka多节点服务
配置多节点服务,拷贝出2份配置server1.properties,server2.properties,修改2处参数
------------------------------server1.properties
broker.id=1
listeners=PLAINTEXT://:9092
log.dirs=/tmp/kafka1-logs
------------------------------server2.properties
broker.id=2
listeners=PLAINTEXT://:9093
log.dirs=/tmp/kafka2-logs
-----------------------------
2)启动zookeeper服务
bin/zookeeper-server-start.sh config/zookeeper.properties
3)启动2个kafka服务
bin/kafka-server-start.sh config/server1.properties
bin/kafka-server-start.sh config/server2.properties
4)创建topic主题
bin/kafka-topics.sh --create --zookeeper kafka01:2181 -replication-factor 1 --partitions 1 --test2
5)启动生产者
bin/kafka-console-producer.sh --broker-list kafka02:9093 --topic test2
输入内容
6)启动消费者
bin/kafka-console-consumer.sh --zookeeper kafka01:2181 --topitc test2 --from-beginning
2) 测试多节点可用性
在生产者输入内容,消费者端可以获取到消息
生产者端:



消费者端:

3)测试多节点容错性
杀掉一个kafka服务,然后发送消息测试,消费者是否能政策收到消息

2.3 Kafka分布式集群构建

2.3.1 Kafka分布式集群构建
1.配置zookeeper集群
1)解压后,配置zoo.cfg,如果没有从模板配置文件中拷贝出来
官网建议使用zookeeper3.4.x,3.4.9
http://kafka.apache.org/documentation.html#zk
这里有各种版本的下载地址
https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/
我们需要的版本3.4.9
https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz
配置之前创建目录
命令:mkdir -p /usr/local/hadoop/zookeeper/data /usr/local/hadoop/zookeeper/log
修改zoo.cfg配置
命令:vi /usr/local/hadoop/zookeeper/zookeeper-3.4.5-cdh5.4.5/conf/zoo.cfg
内容:
----------------------------
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/hadoop/zookeeper/data
dataLogDir=/usr/local/hadoop/zookeeper/log
clientPort=2181
server.1=kafka01:2287:3387
server.2=kafka02:2288:3387
server.3=kafka03:2289:3387
----------------------------
b.配置myid(在每个节点上都这样配置)
还有一个关键的设置,在每个zk server配置文件的dataDir所对应的目录下,必须创建一个名为myid的文件,其中的内容必须与zoo.cfg中server.x 中的x相同,即:
-----------------------
/usr/local/hadoop/zookeeper/data/myid 中的内容为1,对应server.1中的1
/usr/local/hadoop/zookeeper/data/myid 中的内容为2,对应server.2中的2
/usr/local/hadoop/zookeeper/data/myid 中的内容为3,对应server.3中的3
-----------------------
c.关闭防火墙,并且各节点要配置好jdk
-------------
service iptables stop
chkconfig iptables off
-------------
d.启动zookeeper
/usr/local/hadoop/zookeeper/zookeeper-3.4.5-cdh5.4.5/bin/zkServer.sh start
e.验证服务
命令1:bin/zkServer.sh status
命令2:bin/zkServer.sh start
f.配置环境变量到/etc/profile
ZOOKEEPER_HOME=/usr/local/hadoop/zookeeper/zookeeper-3.3.6
PATH=$ZOOKEEPER_HOME/bin:$PATH
export PATH
KAFKA_HOME=/usr/local/hadoop/kafka/kafka_2.12-0.10.2.1
PATH=$KAFKA_HOME/bin:$PATH
export PATH

2.配置kafka集群
1)准备目录
命令:mkdir -p /usr/local/hadoop/kafka/log
2)修改server.properties 3个参数,
每个节点的broker.id不一样,本次实验kafka01,kafka02,kafka03对应1,2,3
------------
broker.id=03
log.dirs=/usr/local/hadoop/kafka/log
zookeeper.connect=kafka01:2181,kafka02:2181,kafka03:2181
------------
3)启动kafka集群
每一个节点执行,
命令:bin/kafka-server-start.sh config/server.properties
4)验证kafka集群是否正常启动
a.jps查看进程是否启动,正常启动,会有Kafka进程服务
b.查看/usr/local/hadoop/kafka/log下面是否有数据

2.3.2 Kafka主题创建
1)相关命令
创建命令
bin/kafka-topics.sh --create --zookeeper kafka01:2181 -replication-factor 3 --partitions 2 --topic test3
查看命令
bin/kafka-topics.sh --list  --zookeeper kafka01:2181
查看分区个数、副本个数
bin/kafka-topics.sh --describe --zookeeper kafka01:2181 --topic test

2)相关说明


从这里可以看到很多关于主题的信息,总要包含:
· 主题的leader:读写都从这里进行随机选择
· 主题的副本数:副本数,节点列表
· isr:同步复制
· 主题的分区数:2个分区
zk保留了副本之间的leader和随从信息,每个副本周期性同步到磁盘
1.每个分区有N个副本,可以承受N-1个节点故障,ZK承受N-1/2个故障,如果3个节点,挂了2个,那就不行了。每个副本都有自己的leader,其余的都是follower,zk存放分区的leader和all replica的信息
2.每个副本存储消息的部分数据在本地的log和offset中,周期性同步到磁盘中去确保消息写入全部副本或者其中一个
3.leader故障时,消息或者写入本地log,或则在producer在收到ack消息前,从新发送消息给新的leader这些信息都是保留在zookeeper中的。进一步去zookeeper观察看到有2个topic

再看看kafka的log目录, 实际的数据是保存在kafka的log目录下,虽然还没有写数据,但是相关目录已经准备好了相关存放文件和目录了。


2.3.3 生产者生产数据
1)相关命令
bin/kafka-console-producer.sh --broker-list kafka02:9092 --topic test2
这里要注意端口要和配置文件的保持一致,笔者因为前面演示了单机版的多broker(9093端口),端口没有改正,导致消费者没法消费数据,白白浪费了很多时间排查问题。
2)相关说明
从命令可以看出,生产者是和broker直接交互,broker使用zk协同工具来管理多个broker
broker:broker不知道谁消费了消息,并不维护哪个消费者消费了消息
消费者组:每个组中只有一个消费者可以消费消息(所有的消费者都在一个组》队列模式,都有自己的组》订阅模式),通过消费者组同意了
消费者:维护了消费消息的状态,broker不知道谁消费了消息,并不维护哪个消费者消费了消息,消费者自己知道的。
2.2.4 消费者消费数据
1)相关命令
bin/kafka-console-consumer.sh --zookeeper kafka02:2181 --topic test2 --from-beginning
2)相关说明
1.消息缓存与filesystem的存储,数据是立即被即刻写入OS的内核页并且缓存以及清理磁盘(可以配置)
2.消息被消费后,kafka能长时间驻留消息在服务器,允许重复消费
3.对分组消息使用了消息set,防止网络过载
4.在服务器存放消费的信息,kafka是在消费者端存放,消费者保持消息的状态
5.消费者状态默认是在zk中,也允许存到到其他OLTP,比如数据库
6.Kafka中生产和消费是点心的pull-push
生产者pull(write,输入流),消费者push(read,输出流,拉)
7.没有主从模式,所有的broker的地位相同,broker数据均在zk中维护
并在producer之间共享

8.负载均衡策略,loadbalance,允许producer动态发现broker
9.producer生产者维护了一个broker连接池,并能通过zk的callback进行实时更新
10.producer可以选择同步或者异步的方式发送消息给broker
打电话:同步,阻塞的都是同步的,NIO的特点就是非阻塞,IO就是阻塞的
发短息:异步,你收不收,知不知道,我不管,我先去干其他的事情

2.2.5  消息的压缩
Kafka设计的初衷是迅速处理短小的消息,一般10K大小的消息吞吐性能最好(可参见LinkedIn的kafka性能测试)。但有时候,我们需要处理更大的消息,比如XML文档或JSON内容,一个消息差不多有10-100M,这种情况下,Kakfa应该如何处理?
kafka producer设置compression.type=snappy

2.4 Kafka在ZK目录节点
2.4.1 kafka镜像原理
将元集群的数据副本化给target kafka集群,目标kafka集群就当作一个消费者消费数据实现数据的备份。


2.4.2  Kafka副本模型
同步模型(同步复制):生产者从zk找leader,并发送message,消息立即写入本地log,follow开始拉取消息,每个follow将消息写入各自本地的log,向leader发送确认回执。leader在收到所有的follow的确认回执和本地副本写入工作均完成后,再向producer发送确认回执。 生产者客户端是阻塞的,消费者的数据pull从leader中完成。

异步模型:leader的本地log写入完成马上向生产者发送回执,leader不等待follow的回执,follow行不行,成不成功,不管。
2.4.3 在ZK目录节点内容


/brokers/topics/topic: 存储某个topic的partitions所有分配信息
/brokers/topics/[topic]/partitions/[0...N]: partitions状态信息
/brokers/ids/[0...N]:每个broker的配置文件中都需要指定一个数字类型的id(全局不可重复), 此节点为临时znode(EPHEMERAL).
/controller_epoch -> int (epoch) :此值为一个数字,kafka集群中第一个broker第一次启动时为1,以后只要集群中center controller中央控制器所在broker变更或挂掉,就会重新选举新的center controller,每次center controller变更controller_epoch值就会 + 1;
/controller -> int (broker id of the controller):存储center controller中央控制器所在kafka broker的信息

2.5 实体间交互流程
zookeeper在kafka扮演重要角色,Kafka使用zookeeper作为其分布式协调框架,很好的将消息生产、消息存储、消息消费的过程结合在一起。同时借助zookeeper,kafka能够生产者、消费者和broker在内的所以组件在无状态的情况下,建立起生产者和消费者的订阅关系,并实现生产者与消费者的负载均衡。

2.5.1主题与zk 
在kafka中, 用户可以自定义多个topic,每个topic又可以划分为多个分区,一般情况下,每个分区存储在一个独立的broker上。 所有这些topic与broker的对应关系都有zookeeper进行维护。
在zookeeper中,建立专门的节点来记录这些信息,其节点路径为/brokers/topics/{topic_name},如:

[zk: localhost:2181(CONNECTED) 6] ls /brokers/topics
[toptic_t, test, my-replicated-topic, mykafka, mykafka6, mykafka5, mykafka4, test6, mykafka3, test7, mykafka2]
[zk: localhost:2181(CONNECTED) 17] get /brokers/topics/mykafka4  
{"version":1,"partitions":{"1":[102,103,104],"2":[103,104,102],"0":[104,102,103]}}


针对 topic 的每一个分区与broker的对应关系,zookeeper通过节点 /brokers/topics/topic.name来记录,如:
当broker启动时,会到对应topic节点下注册自己的broker.id到对应分区的isr列表中,如:

[zk: localhost:2181(CONNECTED) 23] get /brokers/topics/mykafka4/partitions/1/state
{"controller_epoch":15,"leader":102,"version":1,"leader_epoch":2,"isr":[102,103,104]}


同样的,当broker退出时,也会触发zookeeper更新其对应topic分区的isr列表,并决定是否需要做消费者的负载均衡。

2.5.2 消费者与zk
注册新的消费者分组
当新的消费者组注册到zookeeper中时,zookeeper会创建专用的节点来保存相关信息,其节点路径为ls /consumers/{group_id},其节点下有三个子节点,分别为[ids, owners, offsets]。
Ø ids节点:记录该消费组中当前正在消费的消费者;
Ø owners节点:记录该消费组消费的topic信息;
Ø offsets节点:记录每个topic的每个分区的offset,如:
[zk: localhost:2181(CONNECTED) 54] get /consumers/test-consumer2-group/offsets/mykafka4/0
142

注册新的消费者
当新的消费者注册到kafka中时,会在/consumers/{group_id}/ids节点下创建临时子节点,并记录相关信息,如:

[zk: localhost:2181(CONNECTED) 57] ls /consumers/test-consumer2-group/ids/test-consumer2-group_dev103-1433562901087-7b517b97
[]
[zk: localhost:2181(CONNECTED) 58] get /consumers/test-consumer2-group/ids/test-consumer2-group_dev103-1433562901087-7b517b97
{"version":1,"subscription":{"mykafka5":1},"pattern":"white_list","timestamp":"1433562901290"}


监听消费者分组中消费者的变化
每个消费者都要关注其所属消费者组中消费者数目的变化,即监听/consumers/{group_id}/ids下子节点的变化。一单发现消费者新增或减少,就会触发消费者的负载均衡。

2.5.3 broker与zk
为了记录broker的注册信息,在zookeeper上,专门创建了属于kafka的一个节点,其路径为/brokers,如:
[zk: localhost:2181(CONNECTED) 1] ls /brokers
[ids, topics]


Kafka的每个broker启动时,都会到zookeeper中进行注册,告诉zookeeper其broker.id, 在整个集群中,broker.id应该全局唯一,并在zookeeper上创建其属于自己的节点,其节点路径为 /brokers/ids/{broker.id}. 如:
[zk: localhost:2181(CONNECTED) 2] ls /brokers/ids
[102, 103]


创建完节点后,kafka会将该broker的broker.name及端口号记录到该节点,如
[zk: localhost:2181(CONNECTED) 4] get /brokers/ids/102
{"jmx_port":-1,"timestamp":"1433209686575","host":"host102","version":1,"port":9092}


另外,该broker节点属性为临时节点,当broker会话失效时,zookeeper会删除该节点,这样,我们就可以很方便的监控到broker节点的变化,及时调整负载均衡等。

2.5.4 消费者与消费者组



a.每个consumer客户端被创建时,会向zookeeper注册自己的信息;
b.此作用主要是为了"负载均衡".
c.同一个Consumer Group中的Consumers,Kafka将相应Topic中的每个消息只发送给其中一个Consumer。
d.Consumer Group中的每个Consumer读取Topic的一个或多个Partitions,并且是唯一的Consumer;
e.一个Consumer group的多个consumer的所有线程依次有序地消费一个topic的所有partitions,如果Consumer group中所有consumer总线程大于partitions数量,则会出现空闲情况;

举例说明:
kafka集群中创建一个topic为report-log 4 partitions 索引编号为0,1,2,3
假如有目前有三个消费者node:注意: 一个consumer中一个消费线程可以消费一个或多个partition.
如果每个consumer创建一个consumer thread线程,各个node消费情况如下,node1消费索引编号为0,1分区,node2费索引编号为2,node3费索引编号为3
如果每个consumer创建2个consumer thread线程,各个node消费情况如下(是从consumer node先后启动状态来确定的),node1消费索引编号为0,1分区;node2费索引编号为2,3;node3为空闲状态

总结:
从以上可知, Consumer Group中各个consumer是根据先后启动的顺序有序消费一个topic的所有partitions的。
如果Consumer Group中所有consumer的总线程数大于partitions数量,则可能consumer thread或consumer会出现空闲状态。

Consumer均衡算法
当一个group中,有consumer加入或者离开时,会触发partitions均衡。 均衡的最终目的,是提升topic的并发消费能力。
1) 假如topic1,具有如下partitions: P0,P1,P2,P3
2) 加入group中,有如下consumer: C0,C1
3) 首先根据partition索引号对partitions排序: P0,P1,P2,P3
4) 根据(consumer.id + '-'+ thread序号)排序: C0,C1
5) 计算倍数: M = [P0,P1,P2,P3].size / [C0,C1].size,本例值M=2(向上取整)
6) 然后依次分配partitions: C0 = [P0,P1],C1=[P2,P3],即Ci = [P(i * M),P((i + 1) * M -1)]

转自: http://mp.weixin.qq.com/s?__biz=MzIzNzI1NzY3Nw==&mid=2247484070&idx=1&sn=fe6f1b5004c75cc78c99147626b1da36&chksm=e8ca1404dfbd9d12ef33324e67e17c6c7a2fc322ea19a04d8eb2af669ab788d4b42d5d19ec32&mpshare=1&scene=23&srcid=0502QfgQPsbjiQRsZmlnBh1x#rd

猜你喜欢

转载自forlan.iteye.com/blog/2372221
今日推荐