> 技术文档 > Kafka详解_kafka是什么

Kafka详解_kafka是什么


一、Kafka 是什么?有什么作用?

Kafka 是一个分布式的流式处理平台,它以高吞吐、可持久化、可水平扩展、支持流数据处理等多种特性而被广泛使用
主要功能体现于三点:

消息系统:

Kafka与传统的消息中间件都具备系统解耦、冗余存储、流量削峰、缓冲、异步通信、扩展性、可恢复性等功能。与此同时,Kafka还提供了大多数消息系统难以实现的消息顺序性保障及回溯性消费的功能。

存储系统:

Kafka把消息持久化到磁盘,相比于其他基于内存存储的系统而言,有效的降低了消息丢失的风险。这得益于其消息持久化和多副本机制。也可以将Kafka作为长期的存储系统来使用,只需要把对应的数据保留策略设置为“永久”或启用主题日志压缩功能。

流式处理平台:

Kafka为流行的流式处理框架提供了可靠的数据来源,还提供了一个完整的流式处理框架,比如窗口、连接、变换和聚合等各类操作。

Kafka 基本概念(术语):

Producer :

生产者,负责将消息发送到 Broker;
Consumer :

消费者,从 Broker 接收消息;
Consumer Group :

消费者组,由多个 Consumer 组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者;
Broker :

可以看做一个独立的 Kafka 服务节点或 Kafka 服务实例。如果一台服务器上只部署了一个 Kafka 实例,那么也可以将 Broker 看做一台 Kafka 服务器;
Topic :

一个逻辑上的概念,包含很多 Partition,同一个 Topic 下的 Partiton 的消息内容是不相同的;
Partition :

为了实现扩展性,一个非常大的 topic 可以分布到多个 broker 上,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列;
Replica :

副本,同一分区的不同副本保存的是相同的消息,为保证集群中的某个节点发生故障时,该节点上的 partition 数据不丢失,且 Kafka 仍然能够继续工作,Kafka 提供了副本机制,一个 topic 的每个分区都有若干个副本,一个 leader 和若干个 follower;
Leader :

每个分区的多个副本中的\"主副本\",生产者以及消费者只与 Leader 交互;
Follower :

每个分区的多个副本中的\"从副本\",负责实时从 Leader 中同步数据,保持和 Leader 数据的同步。Leader 发生故障时,从 Follower 副本中重新选举新的 Leader 副本对外提供服务。

二、Kafka 的可靠性是怎么保证的?怎么保证Kafka消息不丢失

(1)acks

        这个参数用来指定分区中有多少个副本收到这条消息,生产者才认为这条消息是写入成功的,这个参数有三个值:
        acks = 1,默认为1:生产者发送消息,只要 leader 副本成功写入消息,就代表成功。这种方案的问题在于,当返回成功后,
        如果 leader 副本和 follower 副本还没有来得及同步,leader 就崩溃了,那么在选举后新的 leader 就没有这条消息,也就丢失了;
        acks = 0:生产者发送消息后直接算写入成功,不需要等待响应。这个方案的问题很明显,只要服务端写消息时出现任何问题,都会导致消息丢失;
        acks = -1 或 acks = all:生产者发送消息后,需要等待 ISR 中的所有副本都成功写入消息后才能收到服务端的响应。毫无疑问这种方案的可靠性是最高的,
        但是如果 ISR 中只有leader 副本,那么就和 acks = 1 毫无差别了。

(2)生产者发送消息有三种方式,发完即忘,同步和异步。可以通过同步或者异步获取响应结果,失败做重试来保证消息的可靠性。

(3)消费者默认是 自动按期提交已经消费的偏移量,默认每隔5s提交一次,有可能会出现重复消费或者丢失数据的情况,尽量手动提交


三、Kafka怎么保证不重复消费

为什么 Kafka 会重复消费:
1.消费者崩溃,在消费完消息但尚未提交 offset 前崩溃,重启后会重新拉取这条消息。
2.提交偏移量失败,自动提交或手动提交失败,导致下次再次消费到相同的消息。
3.自动提交消费位移
kafka默认消费位移的提交是自动提交,由消费者参数enable.auto.commit配置,默认为true。
这个自动提交并不是每消费一条消息就自动提交消费位移,而是定期提交,这个定期提交的时间由客户端参数
auto.commit.interval.ms配置,默认5秒。也就是说,在默认情况下,消费者每隔5秒会将拉取到的每个分区中最大的消息位移进行提交。
注意:自动提交的动作在poll()方法的逻辑中,在每次向服务器端发起拉取请求之前会检查是否可以进行位移提交,如果可以就提交上一次轮询的位移。
如果在拉取消息进行消费,但是下一次提交位移之前消费者崩溃了,或者在消费者关闭之前调用了
consumer.unsubscribe()方法取消订阅,那么下一次就还得在上一次消费位移的位置重新开始消费,造成重复消费

(1)幂等性(Idempotence)【生产者】
Kafka 的生产者可以通过设置 enable.idempotence=true 来开启幂等性。开启后,Kafka 会为每条消息分配一个唯一的序列号(Sequence Number),
Broker 会根据序列号去重,确保同一条消息不会被重复写入。保证在单分区单会话中保证不重复。props.put(\"enable.idempotence\", true); // 开启幂等性
(2)手动提交偏移量(Offset)【消费者】
Kafka 消费者默认是自动提交偏移量的,但这可能会导致消息被重复消费。比如,消费者处理完消息但还没来得及提交偏移量就崩溃了,重启后就会重新消费这些消息。
为了避免这种情况,我们可以改为手动提交偏移量,确保消息处理完成后再提交。

四、如何保证消费的顺序性

Topic分区中消息只能由消费者组中的唯一 一个消费者处理,所以消息肯定是按照先后顺序进行处理的。但是它也仅仅是保证Topic的一个分区顺序处理,不能保证跨分区的消息先后处理顺序。所以,如果你想要顺序的处理Topic的所有消息,那就只提供一个分区。

//指定分区
kafkaTemplate.send( topic:\"springboot-kafka-topic\",partition: 0,key:\"key-001\", data: \"value-0001\");
//相同的业务key
kafkaTemplate.send( topic:\"springboot-kafka-topic\",key:\"key-001\",data:\"value-0001\");

kafka默认存储和消费消息,是不能保证顺序性的,因为一个topic数据可能存储在不同的分区中,每个分区都有一个按照顺序的存储的偏移量,如果消费者关联了多个分区不能保证顺序性,如果有这样的需求的话,我们是可以解决的,把消息都存储同一个分区下就行了,有两种方式都可以
进行设置,第一个是发送消息时指定分区号,第二个是发送消息时按照相同的业务设置相同的key,因为默认情况下分区也是通过key的hashcode值来选择分区的,hash值如果一样的话,分区肯定也是一样的。
 

五、Kafka高持久性的原因

一、集群模式

二、分区备份机制

总结: