摘要
官网链接 Apache Kakfa
本文主要介绍了如下内容
-
Kafka 的简单介绍
-
Kafka中重要的基本名词概念,并给出了个人的一些分析
如果疑议,欢迎gitee 提 issue,共同进步
Kafka是什么
首先你要知道什么是消息队列
一个分布式的消息队列技术组件,起源于领英,最开始是为了处理海量日志问题,后边逐渐进化成为业界一流的消息队列中间件。
应用场景
业务解耦:用于解耦不同业务系统,提供异步调用,通知的能力
数据处理:参与构建像Flink这样的流处理任务,可以作为实时数据源提供流式数据
基本概念
kafka 的几个基本概念
- topic:消息话题,定义了一个消息名称
- producer:消息制造者
- consumer:消息消费者
- broker:接受,分发消息的机器,物理上可以理解为kafka的server
- partition:消息分区
- replica:消息分区的副本
Topic
消息话题?因为他有点儿类似map里的key,代表了一个消息类型,但是不是具体的消息内容 后边的发送消息,消费消息,都需要指定Topic 创建Topic命令是这样的
# 你看,指定了Topic,以及kafka集群。你可可能看到 之前是ZK 的地址,这个官方已经替换掉了 https://cwiki.apache.org/confluence/display/KAFKA/KIP-377%3A+TopicCommand+to+use+AdminClient
$ bin/kafka-topics.sh --create --topic quickstart-events --bootstrap-server localhost:9092
Producer(消息制造者)
人如其名,负责向消息队列提交消息,启动一个producer 的时候会指定Topic,从而确定向哪个Topic发送消息。比如启动一个Producer的命令是这样的
bin/kafka-console-producer.sh --topic quickstart-events --bootstrap-server localhost:9092
这个命令会给你建立起一个长链接,然后你就能随便输入,每次回车都会发送一个消息到消息队列中。想结束的话 Ctrl+C
Consumer(消费者)
同样的人如其名,负责消费Kafka消息,一般来说,消费者会解析订阅Topic,然后处理真正的消息(Message),命令如下
# 注意,消费者特别指定了从头开始消费哦
$ bin/kafka-console-consumer.sh --topic quickstart-events --from-beginning --bootstrap-server localhost:9092
想结束的话 Ctrl+C
Broker
负责存储具体消息数据,偏向于物理层面(非逻辑层),一个Broker可以理解为一个Kafka Server 进程或者一台运行这Kafka 服务的机器
Partition(分区)
这个更倾向于是一个逻辑概念,首先一个消息可以有多个分区,每个分区会真正存储在某一个Broker上,所以最终的效果就是一个Topic对应的Message水平的分布在Broker上 为什么要水平分区? 主要是为了提高吞吐量。一般来讲(也可以从业务需求来说),业务消息生产的速率会往往远大于消费速度,也就是不会限制同一时刻前端有多少用户操作。比如没有产品会限制QPS,所有人都希望越高越好。但是后端服务可能并不能完全处理,所以Kafka 分区主要解决的是就是通过尽可能多的将消息积压起来,先完成核心业务,其他业务通过异步接收消息慢慢处理。同时引入了分区对消息进行水平分散,不仅多个Producer 能够并行像多个分区发送消息,多个Consumer也能够并行的从多个分区进行消费。另外分区也保证了负载均衡,不会让某一台机器存储过大过多的数据 另外通过分区机制,也可以实现资源倾斜,即量大的Topic分配更多的分区提高吞吐量,量小的分配更少的分区。
分区有没有问题 ? 有的,但是不严重。主要就是消息的全局有序性,对于同一Topic的消息来说,没办法保证消息A到达集群的时间早于消息B时,消息A就一定能够早于消息B被消费,存在两种情况
- 消息A,B 在同一个分区上 1. kafka 分区都有OffSet,通过Offset kafka分区的消息是有序的(到达的顺序),所以此时消息A一定早于消息B 分发给消费者
- 消息A,B 在不同分区上 1. 不同分区之间,没有也不会有机制来保障分发到Consumer的顺序(会影响整体的吞吐量),所以此时没法保证消息A,B的消费顺序 所以如果你需要让消息进行有序消费,那么就需要让相同规则的消息发送到同一分区,比如按uid取模。在Java API 内可以自定义producer的规则
Replica(副本)
副本=不生效的分区。副本其实全称是 【分区的副本】,它的作用就是保证消息不会丢失。上边说到了分区的概念,但是如果每个分区只有一个副本(也就是自己本身),那么风险是比较高的,对于发送到它身上的消息来说,它就是单点了,而kafka处理的场景一定是具有极大数据量,那么就需要引入副本机制,对分区进行多个备份,来保证数据不丢失 因为一个分区存在多个副本,那么当一个消费者确定消费某一个分区时,到底是哪个副本响应请求呢?一个还是多个还是全部?又分别有什么问题呢?
- 一个副本响应请求 1. 需要解决选主问题,即以谁为准? 1. ZK 可以解决 2. 问题:资源浪费,其他副本并不响应消费请求
- 多个副本响应请求 1. 怎么决定谁来响应请求?谁不响应请求? 1. 无法决策,分布式目前都是解决从集群中选出一个,还不支持选出多个 2. 如果只有一个主节点的话,主节点挂了能立刻选择,如果多个,肯定会出现数据不一致的问题,即同一时间,有的副本写入了,有的副本没写入,然后分区有序性也被破坏了
- 所有副本分别响应请求 1. 大家都是leader? 1. 数据一致的问题,有的副本能读到,有的读不到 2. 那我能不能让所有的副本都同步之后,再消费?那就回到了最开始说的,消费端一定比生产端慢,降低了生产端的吞吐量属于本末倒置
所以,Kafka 实际是第一种策略,也就是一主多从。同一时刻只有一个leader 节点负责响应请求,其它副本只负责自己尽量和leader节点保持一致。后边会讲详细的细节
总结
上边基本把Kafka涉及到的角色术语都介绍了一下,但是还有很多重要的细节没有介绍,比如
- Kafka的消息是持久化磁盘上的,那么到底做了哪些优化来实现在廉价的磁盘上实现高速的写入?
- Kafka 的副本机制,是怎么保证消息的不丢失的?
- Kafka 都能提供什么样的消息交付?能否保证消息在任何情况下都只发送一次,然后只被消费一次?
- 副本的Leader 是怎么选举的?
- 分区会出现负载不均衡的情况,那么是怎么Rebalance的?
- Comsumer是怎么确定自己消费哪个分区的?