springboot整合kafka

一、概述

在深入理解Kafka之前,先介绍一下Kafka中的术语。下图展示了Kafka的相关术语以及之间的关系:

上图中一个topic配置了3个partition。Partition1有两个offset:0和1。Partition2有4个offset。Partition3有1个offset。副本的id和副本所在的机器的id恰好相同。

如果一个topic的副本数为3,那么Kafka将在集群中为每个partition创建3个相同的副本。集群中的每个broker存储一个或多个partition。多个producer和consumer可同时生产和消费数据。

1、broker

Kafka 集群包含一个或多个服务器,服务器节点称为broker。

broker存储topic的数据。如果某topic有N个partition,集群有N个broker,那么每个broker存储该topic的一个partition。

如果某topic有N个partition,集群有(N+M)个broker,那么其中有N个broker存储该topic的一个partition,剩下的M个broker不存储该topic的partition数据。

如果某topic有N个partition,集群中broker数目少于N个,那么一个broker存储该topic的一个或多个partition。在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致Kafka集群数据不均衡。

2、Topic

每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)

类似于数据库的表名

3、Partition

topic中的数据分割为一个或多个partition。每个topic至少有一个partition。每个partition中的数据使用多个segment文件存储。partition中的数据是有序的,不同partition间的数据丢失了数据的顺序。如果topic有多个partition,消费数据时就不能保证数据的顺序。在需要严格保证消息的消费顺序的场景下,需要将partition数目设为1。

4、Producer

生产者即数据的发布者,该角色将消息发布到Kafka的topic中。broker接收到生产者发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中。生产者发送的消息,存储到一个partition中,生产者也可以指定数据存储的partition。

5、Consumer

消费者可以从broker中读取数据。消费者可以消费多个topic中的数据。

6、Consumer Group

每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。

如果分区数大于或者等于组中的消费者实例数,那自然没有什么问题,无非一个消费者会负责多个分区,(PS:当然,最理想的情况是二者数量相等,这样就相当于一个消费者负责一个分区);但是,如果消费者实例的数量大于分区数,那么按照默认的策略(PS:之所以强调默认策略是因为你也可以自定义策略),有一些消费者是多余的,一直接不到消息而处于空闲状态。

Kafka分区分配策略

在 Kafka 内部存在两种默认的分区分配策略:Range 和 RoundRobin。当以下事件发生时,Kafka 将会进行一次分区分配:

6.1RoundRobin(轮循分配):

这个分区分配策略简单来说就是列出所有的分区,然后和消费线程之间进行循环的分配即可。

如果你需要使用该分配策略,你需要满足所有的消费线程都是消费相同的topic,且每个消费者之间的消费线程数是一样的。

6.2Range(范围策略)

上述简单来说就是分区总数/消费线程数,如果有余,则表明有的消费线程之间分配的分区不均匀,那么这个多出来的分区会给前几个消费线程处理。

比如上述5个分区,2个comsumer,4个消费线程,则5/4=1,这个表明如果4个消费线程均分5个分区还会多出一个分区,

那么这个多出的额外分区就会给前面的消费线程处理,所以它会把第一个分区先给到c1-0消费线程消费。

也可以这样的认为分配:

5/4余1,则分配规则为2,1,1,1,对应的消费线程为C1-0,C1-1,C2-0,C2-1

如果是6个分区的话:

6/4余2,则分配规则为2,2,1,1,对应的消费线程为C1-0,C1-1,C2-0,C2-1

7、Leader

每个partition有多个副本,其中有且仅有一个作为Leader,Leader是当前负责数据的读写的partition。

8、Follower

Follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower,Follower与Leader保持数据同步。如果Leader失效,则从Follower中选举出一个新的Leader。当Follower与Leader挂掉、卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower。

二、kafka与RabbitMq的区别

1、异同点

1.1架构模型

RabbitMQ遵循AMQP协议,RabbitMQ的broker由Exchange,Binding,queue组成,其中exchange和binding组成了消息的路由键;客户端Producer通过连接channel和server进行通信,Consumer从queue获取消息进行消费(长连接,queue有消息会推送到consumer端,consumer循环从输入流读取数据)。rabbitMQ以broker为中心。

Kafka遵从一般的MQ结构,producer,broker,consumer,以consumer为中心,消息的消费信息保存的客户端consumer上,consumer根据消费的点,从broker上批量pull数据。
 

1.2消息确认机制

RabbitMQ具有生产者confirm机制以及消费者的消息应答机制ack。

Kafka不具有应答机制。

1.3消息的顺序

RabbitMQ中,在一个队列里面,rabbitmq的消息是严格顺序的,按照先进先出。

Kafka中,在同一个partition中消息是有序的,但是生产者put到Kafka中数据会分布在不同的partition中,所有总体是无序的。

1.4吞吐量

根据测试,RabbitMQ在不使用ACK机制的,Msg大小为1K的情况下,QPS可达6W+。再双方ACK机制,Msg大小为1K的情况下,QPS瞬间降到了1W+。

Kafka具有巨大的吞吐量,数据的存储以及获取是本地磁盘的批量处理,可以达到百万/s。

1.5可靠性

RabbitMQ使用了MirrorQueue的机制,也可以做到多个机器进行热备。

Kafka的broker支持主备模式。

1.6持久化

RabbitMQ支持持久化。

Kafka 是一个持久性消息存储。

2、使用场景

1.RabbitMQ的消息应当尽可能的小,并且只用来处理实时且要高可靠性的消息。 2.消费者和生产者的能力尽量对等,否则消息堆积会严重影响RabbitMQ的性能。 3.集群部署,使用热备,保证消息的可靠性。

1.应当有一个非常好的运维监控系统,不单单要监控Kafka本身,还要监控Zookeeper。(kafka强烈的依赖于zookeeper,如果zookeeper挂掉了,那么Kafka也不行了)
 
2.对消息顺序不依赖,且不是那么实时的系统。
 
3.对消息丢失并不那么敏感的系统。
 
4.从 A 到 B 的流传输,无需复杂的路由,最大吞吐量可达每秒 100k 以上。

三、Spring Boot整合Kafaka

1、Maven准备

       <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
            <version>1.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2、配置文件


#============== kafka ===================
# 指定kafka 代理地址,可以多个
spring.kafka.bootstrap-servers=192.168.71.129:9092

#=============== provider  =======================

spring.kafka.producer.retries=0
# 每次批量发送消息的数量
spring.kafka.producer.batch-size=16384
spring.kafka.producer.buffer-memory=33554432

# 指定消息key和消息体的编解码方式
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer

#=============== consumer  =======================
# 指定默认消费者group id
spring.kafka.consumer.group-id=test-consumer-group

spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.enable-auto-commit=true
spring.kafka.consumer.auto-commit-interval=100

# 指定消息key和消息体的编解码方式
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer

3、发送者

        @Resource
       private KafkaTemplate<String, String> kafkaTemplate;

        Message message = new Message();
        message.setId( System.currentTimeMillis() );
        message.setMsg( respStr );
        message.setSendTime( new Date() );
        kafkaTemplate.send( "producersToConsumers_logs", gson.toJson( message ) );

4、接受者

    @KafkaListener(topics = {"producersToConsumers_logs"})
    public void listen(ConsumerRecord<?, ?> record) {
        Optional<?> optional = Optional.ofNullable( record.value() );

        if (optional.isPresent()) {
            Object msg = optional.get();
            log.info( "record:{}", record );
            log.info( "message:{}", msg );
        }
    }

5、消息类

@Data
public class Message {

    private long id;

    private String msg;

    private Date SendTime;


}

6、在虚拟机中,查看接受者是否接受成功

######启动zookeeper
bin/zookeeper-server-start.sh -daemon  config/zookeeper.properties
#####启动kafka服务
bin/kafka-server-start.sh config/server.properties
#####查看集合
bin/kafka-topics.sh --list --zookeeper  localhost:2181
#####消费者查看信息
bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic producersToConsumers_logs --from-beginning

注意:

ACK有三种

意味着producer不等待broker同步完成的确认,继续发送下一条(批)信息

提供了最低的延迟。但是最弱的持久性,当服务器发生故障时,就很可能发生数据丢失。例如leader已经死亡,producer不知情,还会继续发送消息broker接收不到数据就会数据丢失

1

意味着producer要等待leader成功收到数据并得到确认,才发送下一条message。此选项提供了较好的持久性较低的延迟性。

Partition的Leader死亡,follwer尚未复制,数据就会丢失

-1

意味着producer得到follwer确认,才发送下一条数据

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wwwzhouzy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值