a distributed streaming platform.
Kafka是一种消息队列
,主要用来处理大量数据状态
下的消息队列,一般用来做日志的处理。既然是消息队列,那么Kafka
也就拥有消息队列的相应的特性了。
消息队列的好处:
⚾️ 解藕
⚾️ 异步处理
⚾️ 削峰平谷
Kafka的消费模式主要有两种:一种是一对一的消费,也即点对点的通信,即一个发送一个接收。第二种为一对多的消费,即一个消息发送到消息队列,消费者根据消息队列的订阅拉取消息消费。
**一对一:**消息生产者发布消息到Queue队列中,通知消费者从队列中拉取消息进行消费。消息被消费之后则删除,Queue支持多个消费者,但对于一条消息而言,只有一个消费者可以消费,即一条消息只能被一个消费者消费
。
一对多:这种模式也称为发布/订阅模式,即利用Topic存储消息,消息生产者将消息发布到Topic中,同时有多个消费者订阅此Topic,消费者可以从中消费消息,注意发布到Topic中的消息会被多个消费者消费,消费者消费数据之后,数据不会被清除,Kafka会默认保留一段时间,然后再删除。
Kafka像其他Mq一样,也有自己的基础架构,主要存在生产者Producer、Kafka集群Broker、消费者Consumer、注册消息Zookeeper。
⚾️ Producer:消息生产者,向Kafka中发布消息的角色。
⚾️ Consumer:消息消费者,即从Kafka中拉取消息消费的客户端。
⚾️ Consumer Group:消费者组,消费者组则是一组中存在多个消费者,消费者消费Broker中当前Topic的不同分区中的消息,消费者组之间互不影响,所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。某一个分区中的消息只能够一个消费者组中的一个消费者所消费
⚾️ Broker:经纪人,一台Kafka服务器就是一个Broker,一个集群由多个Broker组成,一个Broker可以容纳多个Topic。
⚾️ Topic:主题,可以理解为一个队列,生产者和消费者都是面向一个Topic
⚾️ Partition:分区,为了实现扩展性,一个非常大的Topic可以分布到多个Broker上,一个Topic可以分为多个Partition,每个Partition是一个有序的队列(分区有序,不能保证全局有序)
⚾️ Replica:副本Replication,为保证集群中某个节点发生故障,节点上的Partition数据不丢失,Kafka可以正常的工作,Kafka提供了副本机制,一个Topic的每个分区有若干个副本,一个Leader和多个Follower
⚾️ Leader:每个分区多个副本的主角色,生产者发送数据的对象,以及消费者消费数据的对象都是Leader。
⚾️ Follower:每个分区多个副本的从角色,实时的从Leader中同步数据,保持和Leader数据的同步,Leader发生故障的时候,某个Follower会成为新的Leader。
上述一个Topic会产生多个分区Partition,分区中分为Leader和Follower,消息一般发送到Leader,Follower通过数据的同步与Leader保持同步,消费的话也是在Leader中发生消费,如果多个消费者,则分别消费Leader和各个Follower中的消息,当Leader发生故障的时候,某个Follower会成为主节点,此时会对齐消息的偏移量。
kafka需要zookeeper管理,所以需要先安装zookeeper
⚾️ 安装zookeeper和kafka
docker pull wurstmeister/zookeeper
docker pull wurstmeister/kafka
⚾️ 启动zookeeper
# 端口映射到本地的2181
docker run -d --name zookeeper -p 2181:2181 -t wurstmeister/zookeeper
⚾️ 启动kafka
# 本机IP使用ifconfig命令查看
docker run -d --name kafka \
-p 9092:9092 \
-e KAFKA_BROKER_ID=0 \
-e KAFKA_ZOOKEEPER_CONNECT=本机ip:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://本机ip:9092 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 wurstmeister/kafka
# 启动示例
docker run -d --name kafka \
-p 9092:9092 \
-e KAFKA_BROKER_ID=0 \
-e KAFKA_ZOOKEEPER_CONNECT=10.31.154.242:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://10.31.154.242:9092 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 wurstmeister/kafka
⚾️ 消息测试
kafka自带了终端工具,在终端测试
# 进入容器
docker exec -it {container-id} bash
# 进入kafka安装目录
cd cd opt/kafka_2.13-2.8.1/bin/
# 创建一个叫test的topic
./kafka-console-producer.sh --broker-list localhost:9092 --topic "test"
# 输入一个消息后确认,然后运行consumer查看是否有消息
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic "test" --from-beginning
# 终端输出刚才输入的内容即为构建成功
参考文档:Kafka-Python Api
⚾️ 构建producer
每一秒向Topic发一条消息
# 由于Kafka的生产者和消费者都需要Topic,所以这边写了一个config
# 内容为:SERVER = '127.0.0.1:9092' TOPIC = 'test'
# producer.py
import json
import time
import datetime
import config
from kafka import KafkaProducer
producer = KafkaProducer(
bootstrap_servers=config.SERVER,
value_serializer=lambda m: json.dumps(m).encode()
)
for i in range(100):
data = {'num': i + 1, 'ts': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "msg": "成功"}
producer.send(config.TOPIC, data)
time.sleep(1)
⚾️ 构建consumer
# consumer.py
import json
from kafka import KafkaConsumer
import config
# 第一个参数为topic的名称
# bootstrap_servers: 指定kafka服务器
# group_id : 指定此消费者实例属于的组名,可以不指定
# auto.offset.reset关乎kafka数据的读取,是一个非常重要的设置。常用的二个值是latest和earliest,默认是latest。
# - earliest 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
# - latest 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
consumer = KafkaConsumer(
config.TOPIC,
bootstrap_servers=config.SERVER,
api_version=(0, 11, 5),
group_id="ichpan",
auto_offset_reset='earliest'
)
for msg in consumer:
print(json.loads(msg.value))
⚾️ 运行之后producer.py,Script会执行你的任务(发送消息),运行consumer.py可以获取到消息!!!(如图)
以上就是一个完整运行Kafka消息队列的全过程,原理和redis发布者订阅者模式差不多,可以理解就是基于Channel的,在使用中我们可以查看容器的log来排除错误信息,也是非常方便的。