Kafka
消息队列的通信模型
点对点模式(queue)
消息生产者生产消息送到queue中,然后消息消费者从queue中取出并且消费。一条消息被消费以后,queue中就没有了,不存在重复消费
发布/订阅(topic)
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
一个topic下有多个Queue,每个Queue是点对点的方式,Queue之间是发布订阅方式
介绍:
Kafka由Linkedln开发,Scala语言编写,Apache顶级项目。是一个分布式数据流平台,可以在单台服务器或者多态服务器上部署。提供了发布和订阅的功能,可以发送数据到Kafka中也可以从Kafka中读取数据。吞吐量高,延迟低,容错高
- Producer: 生产者,消息的生产者,是消息的入口
- kafka cluster: kafka集群,一台或多台服务器组成
- Broker: 节点,每个服务器上有一个或多个kafka的实例,每个broker对应一台服务器。每个kafka集群内的broker都有一个不重复的编号
- Topic: 消息主题,可以理解为消息的分类,kafka的数据就保存在topic。在每个broker上都可以创建多个topic。实际应用中通常是一个业务线建一个topic
- Partition: Topic的分区,每个topic可以有多个分区,分区的作用是做负载,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,partition的表现形式是一个个的文件夹
- Replication: 每一个Partition都有多个副本,副本的作用是做备胎。当leader故障时会选择一个follower成为leader。默认副本的最大数量是10,副本的数量不能大于Broker的数量,follower和leader绝对是在不同的机器上,同一机器只能存一份副本
- Consumer:消费者
- Consumer Group:我们可以将多个消费者组成一个消费者组,同一个分区的数据智能被消费者组中的某个消费者消费。同一个消费者组的消费者可以消费同一个topic的不同分区的数据
工作流程
Producer生产者,在写入数据的时候会把数据写入到leader中,不会直接将数据写入follower
选择partition的原则
- partition在写入的时候可以指定需要写入的partition,如果指定,则写入对应的partition
- 如果没有指定partition,但是设置了数据的key,则会根据key的值hash出一个partition
- 如果既没指定partition,又没指定key,则采用轮询方式,即每次取一小段时间的数据写入某个partition,下一小段的时间写入下一个partition
ACK应答机制
producer在向kafka写入消息的时候,可以设置参数来确定是否确定kafka接收数据,这个参数可以设置的值为0,1,all
- 0代表producer往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高
- 1代表producer往集群发送数据只要leader应答就可以发送下一条,只确保leader发送成功
- all代表producer往集群发送数据需要所有follower都完成从leader的同步才发送下一条,确保leader发送成功和所有副本都完成备份。安全性最高,但是效率最低。
最后要注意的是,如果往不存在的topic写数据,kafka会自动创建topic,partition和replcation的数量,默认配置都是1
Topic和数据日志
topic是同一类别的消息记录的集合。在Kafka中,一个主题通常有多个订阅者。对于每个主题,Kafka集群维护了一个分区数据日志文件结构如下:
每个partition都是一个有序并且不可变的消息记录集合。当新的数据写入时,就被追加到partition的末尾。在每个partition中,每条消息都会被分配一个顺序的唯一标识,这个标识被称为offset。注意:只保证在同一个partition内部消息是有序的,不同partition之间并不能保证。
Kafka可以配置一个保留期限,用来标识日志会在Kafka集群内保留多长时间
Partition结构
Partition在服务器上的表现形式就是一个个文件夹,每个partition的文件夹下面会有多组segment文件,每组segment文件又包含.index文件、.log文件、.timeindex文件三个文件,.index文件和.timeindex文件为索引文件,.log为实际存储message的地方
消费数据
-
多个消费者实例可以组成一个消费者组,并且用一个标签来标识这个消费者组。
-
一个消费者组中的不同消费者实例可以运行在不同的进程甚至不同的服务器上
-
如果所有的消费者实例都在同一个消费者组中,那么消息记录会被很好的均衡的发送到每个消费者实例
-
如果所有的消费者实例都在不同的消费者组,那么每一条消息记录会被广播到每一个消费者实例