kafka-concept

27 阅读6分钟

摘要

官网链接 Apache Kakfa

本文主要介绍了如下内容

  1. Kafka 的简单介绍

  2. 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被消费,存在两种情况

  1. 消息A,B 在同一个分区上 1. kafka 分区都有OffSet,通过Offset kafka分区的消息是有序的(到达的顺序),所以此时消息A一定早于消息B 分发给消费者
  2. 消息A,B 在不同分区上 1. 不同分区之间,没有也不会有机制来保障分发到Consumer的顺序(会影响整体的吞吐量),所以此时没法保证消息A,B的消费顺序 所以如果你需要让消息进行有序消费,那么就需要让相同规则的消息发送到同一分区,比如按uid取模。在Java API 内可以自定义producer的规则

Replica(副本)

副本=不生效的分区。副本其实全称是 【分区的副本】,它的作用就是保证消息不会丢失。上边说到了分区的概念,但是如果每个分区只有一个副本(也就是自己本身),那么风险是比较高的,对于发送到它身上的消息来说,它就是单点了,而kafka处理的场景一定是具有极大数据量,那么就需要引入副本机制,对分区进行多个备份,来保证数据不丢失 因为一个分区存在多个副本,那么当一个消费者确定消费某一个分区时,到底是哪个副本响应请求呢?一个还是多个还是全部?又分别有什么问题呢?

  1. 一个副本响应请求 1. 需要解决选主问题,即以谁为准? 1. ZK 可以解决 2. 问题:资源浪费,其他副本并不响应消费请求
  2. 多个副本响应请求 1. 怎么决定谁来响应请求?谁不响应请求? 1. 无法决策,分布式目前都是解决从集群中选出一个,还不支持选出多个 2. 如果只有一个主节点的话,主节点挂了能立刻选择,如果多个,肯定会出现数据不一致的问题,即同一时间,有的副本写入了,有的副本没写入,然后分区有序性也被破坏了
  3. 所有副本分别响应请求 1. 大家都是leader? 1. 数据一致的问题,有的副本能读到,有的读不到 2. 那我能不能让所有的副本都同步之后,再消费?那就回到了最开始说的,消费端一定比生产端慢,降低了生产端的吞吐量属于本末倒置

所以,Kafka 实际是第一种策略,也就是一主多从。同一时刻只有一个leader 节点负责响应请求,其它副本只负责自己尽量和leader节点保持一致。后边会讲详细的细节

总结

上边基本把Kafka涉及到的角色术语都介绍了一下,但是还有很多重要的细节没有介绍,比如

  1. Kafka的消息是持久化磁盘上的,那么到底做了哪些优化来实现在廉价的磁盘上实现高速的写入?
  2. Kafka 的副本机制,是怎么保证消息的不丢失的?
  3. Kafka 都能提供什么样的消息交付?能否保证消息在任何情况下都只发送一次,然后只被消费一次?
  4. 副本的Leader 是怎么选举的?
  5. 分区会出现负载不均衡的情况,那么是怎么Rebalance的?
  6. Comsumer是怎么确定自己消费哪个分区的?