Kafka的生产者和消费者代码解析

本文详细解析了Kafka的生产者和消费者代码分配逻辑,包括按顺序分配分区的方法,以及Kafka文件存储的基本结构。同时,提供了生产者和消费者的源码示例,并针对运行中遇到的问题进行了故障排除。
摘要由CSDN通过智能技术生成

Kafka的生产者和消费者代码解析

1:Kafka名词解释和工作方式
    1.1:Producer :消息生产者,就是向kafka broker发消息的客户端。
    1.2:Consumer :消息消费者,向kafka broker取消息的客户端
    1.3:Topic :可以理解为一个队列。
    1.4:Consumer Group (CG):这是kafka用来实现一个topic消息的广播(发给所有的consumer)和单播(发给任意一个consumer)的手段。一个topic可以有多个CG。topic的消息会复制(不是真的复制,是概念上的)到所有的CG,但每个partion只会把消息发给该CG中的一个consumer。如果需要实现广播,只要每个consumer有一个独立的CG就可以了。要实现单播只要所有的consumer在同一个CG。用CG还可以将consumer进行自由的分组而不需要多次发送消息到不同的topic。
    1.5:Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic。
    1.6:Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序。
    1.7:Offset:kafka的存储文件都是按照offset.kafka来命名,用offset做名字的好处是方便查找。例如你想找位于2049的位置,只要找到2048.kafka的文件即可。当然the first offset就是00000000000.kafka。

2:Consumer与topic关系?本质上kafka只支持Topic。
  2.1:每个group中可以有多个consumer,每个consumer属于一个consumer group;
通常情况下,一个group中会包含多个consumer,这样不仅可以提高topic中消息的并发消费能力,而且还能提高"故障容错"性,如果group中的某个consumer失效那么其消费的partitions将会有其他consumer自动接管。
2.2:对于Topic中的一条特定的消息,只会被订阅此Topic的每个group中的其中一个consumer消费,此消息不会发送给一个group的多个consumer;
那么一个group中所有的consumer将会交错的消费整个Topic,每个group中consumer消息消费互相独立,我们可以认为一个group是一个"订阅"者。
2.3:在kafka中,一个partition中的消息只会被group中的一个consumer消费(同一时刻);
一个Topic中的每个partions,只会被一个"订阅者"中的一个consumer消费,不过一个consumer可以同时消费多个partitions中的消息。
2.4:kafka的设计原理决定,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息。
  2.5:kafka只能保证一个partition中的消息被某个consumer消费时是顺序的;事实上,从Topic角度来说,当有多个partitions时,消息仍不是全局有序的。

3:Kafka消息的分发,Producer客户端负责消息的分发。
  3.1:kafka集群中的任何一个broker都可以向producer提供metadata信息,这些metadata中包含"集群中存活的servers列表"/"partitions leader列表"等信息;
3.2:当producer获取到metadata信息之后, producer将会和Topic下所有partition leader保持socket连接;
3.3:消息由producer直接通过socket发送到broker,中间不会经过任何"路由层",事实上,消息被路由到哪个partition上由producer客户端决定;
      比如可以采用"random""key-hash""轮询"等,如果一个topic中有多个partitions,那么在producer端实现"消息均衡分发"是必要的。
3.4:在producer端的配置文件中,开发者可以指定partition路由的方式。
  3.5:Producer消息发送的应答机制:
    设置发送数据是否需要服务端的反馈,三个值0,1,-1。
    0: producer不会等待broker发送ack。
    1: 当leader接收到消息之后发送ack。
    -1: 当所有的follower都同步消息成功后发送ack。
        request.required.acks=0。

4:Consumer的负载均衡:
  当一个group中,有consumer加入或者离开时,会触发partitions均衡.均衡的最终目的,是提升topic的并发消费能力:

 步骤如下:
a、假如topic1,具有如下partitions: P0,P1,P2,P3。
b、加入group中,有如下consumer: C1,C2。
c、首先根据partition索引号对partitions排序: P0,P1,P2,P3。
d、根据consumer.id排序: C0,C1。
e、计算倍数: M = [P0,P1,P2,P3].size / [C0,C1].size,本例值M=2(向上取整)。
f、然后依次分配partitions: C0 = [P0,P1],C1=[P2,P3],即Ci = [P(i * M),P((i + 1) * M -1)]。

6:Kafka文件存储基本结构:

  6.1:在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。
  6.2:每个partion(目录)相当于一个巨型文件被平均分配到多个大小相等segment(段)数据文件中。但每个段segment file消息数量不一定相等,这种特性方便old segment file快速被删除。默认保留7天的数据。

  6.3:每个partiton只需要支持顺序读写就行了,segment文件生命周期由服务端配置参数决定。(什么时候创建,什么时候删除)。


1:使用Idea进行开发,源码如下所示,首先加入Kafka必须依赖的包,这句话意味着你必须要先在Idea上面搭建好的你的maven环境:

pom.xml如下所示内容:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.bie</groupId>
 8     <artifactId>storm</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11     <!-- storm的依赖关系 -->
12     <dependencies>
13         <!--storm依赖的包-->
14         <dependency>
15             <groupId>org.apache.storm</groupId>
16             <artifactId>storm-core</artifactId>
17             <version>0.9.5</version>
18             <!--<scope>provided</scope>-->
19         </dependency>
20         <!-- kafka依赖的包-->
21         <dependency>
22             <groupId>org.apache.kafka</groupId>
23             <artifactId>kafka_2.8.2</artifactId>
24             <version>0.8.1</version>
25             <exclusions>
26                 <exclusion>
27                     <artifactId>jmxtools</artifactId>
28                     <groupId>com.sun.jdmk</groupId>
29                 </exclusion>
30                 <exclusion>
31                     <artifactId>jmxri</artifactId>
32                     <groupId>com.sun.jmx</groupId>
33                 </exclusion>
34                 <exclusion>
35                     <artifactId>jms</artifactId>
36                     <groupId>javax.jms</groupId>
37                 </exclusion>
38                 <exclusion>
39                     <groupId>org.apache.zookeeper</groupId>
40                     <artifactId>zookeeper</artifactId>
41                 </exclusion>
42                 <exclusion>
43                     <groupId>org.slf4j</groupId>
44                     <artifactId>slf4j-log4j12</artifactId>
45                 </exclusion>
46                 <exclusion>
47                     <groupId>org.slf4j</groupId>
48                     <artifactId>slf4j-api</artifactId>
49                 </exclusion>
50             </exclusions>
51         </dependency>
52     </dependencies>
53 
54     <!--如果依赖外部包,就打不进去外部包,所以需要引入下面所示-->
55     <build>
56         <plugins>
57             <plugin>
58                 <!--把其他外部依赖的jar包打成一个大jar包-->
59                 <artifactI
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值