kafka简介
kafka是高吞吐的消息队列系统,轻松支持每秒百万级的写入请求,这种特性也使得Kafka在日志处理等海量数据场景广泛应用。kafka依赖于zookeeper运行,zookeeper充当了协调和管理kafka集群的任务,并且存储一些meta信息。此处,因作者能力有限,不详细讨论kafka与zookeeper的内部细节。
kafka采用的是一种发布-订阅的消息发布模型:消息模型中,首先存在一些producer,即消息的生产者,然后将消息写入broker,即kafka集群中的一个或多个节点,进行消息的缓存,最后由consumer(消费者)订阅消息,进行后处理。在broker中,消息的管理通过topic和partition来实现。topic为一个逻辑概念,表示一类消息,topic可以包含多个partition,实现消息的分布式存储及吞吐。producer、topic、partition、consumer的关系如下图所示(参考博客https://www.cnblogs.com/kevingrace/p/9443270.html):
kafka的producer-topic-partition模型有如下几个需要注意的点:
- 同一个producer可以向多个topic写入消息
- 多个producer可以向同一个topic写入消息
- producer写入消息时可以指定partition,因此1、2两点中对同一个topic下的partition也成立
kafka的topic-partition-consumer模型有如下几个需要注意的点:
- consumer具有组的概念,一个consumer group可以包含多个consumer实例;
- 对于同一个topic下的一条消息,只能被一个consumer group中的一个消费者消费;
- 同一个topic下的一条消息,可以被不同consumer group中的消费者消费;
- 在同一个topic下,同一个consumer group中的一个消费者实例可以订阅多个partition;
- 在同一个topic下,一个partition在某一时刻只能被一个consumer group中的一个消费者实例订阅。
因此再进行消息订阅时,最优方案是确保一个topic下的partition数量大于或等于订阅该topic的consumer group中的消费者实例数量,不然就会出现消费者竞争消费的情况。
上面简述了kafka的一些基础知识,下面进入实际代码环节,主要包含四个部分:
- kafka的启动
- kafka中topic的管理
- 生产者代码
- 消费者代码
依赖:
- kafka 2.11
- python 3.7
- python package: kafka-python 1.4.6
kafka的启动
kafka的启动依赖于zookeeper,在最新版的kafka中已经包含了zookeeper,因此无需额外下载。首先需要启动zookeeper:
nohup ./bin/zookeeper-server-start.sh config/zookeeper.properties &
然后启动kafka:
nohup ./bin/kafka-server-start.sh config/server.properties &
topic管理
执行kafka中topic管理的主要是KafkaAdminClient类,简单创建topic的命令如下:
# -*- coding:utf-8 -*-
import kafka
from kafka import KafkaAdminClient
admin = KafkaAdminClient(bootstrap_servers="127.0.0.1:9092")
# admin.delete_topics(["test"]) # 删除特定topic
topic = kafka.admin.NewTopic("test", 3, 1) # 实例化topic对象,3表示分区数量,1为副本数量
admin.create_topics([topic]) # 创建topic
代码执行后,可进入到kafka根路径,查看其中topic的详细信息:
./kafka-topics.sh --describe --zookeeper 127.0.0.1:2181
生产者代码
上述代码创建了名为test的topic,下面我们利用生产者推送消息:
# -*- coding:utf-8 -*-
from kafka import KafkaProducer
import time
producer = KafkaProducer(bootstrap_servers="127.0.0.1:9092") # 创建生产者实例
while True:
current = time.time()
message = "welcome to %s" % current
print(message)
producer.send("test", value=message.encode(), partition=2) # 发送消息,指定topic和partition
time.sleep(1)
消费者代码
上述代码创建了一个生产者,并向名为test的topic下的partition 2推送消息,下面我们利用消费者消费消息:
# -*- coding:utf-8 -*-
import kafka
from kafka import KafkaConsumer
consumer = KafkaConsumer(bootstrap_servers="localhost:9092", group_id="my") # 创建消费者实例,并指定group id
consumer.assign([kafka.TopicPartition("test", 2)]) # 订阅“test” topic下的partition 2消息,
# 阻塞进程,从消费者不断拉取消息
for msg in consumer:
recv = "%s:%d:%d: key=%s value=%s" % (msg.topic, msg.partition, msg.offset, msg.key, msg.value) # 打印消息的topic、partition、offset及其他元信息
print(recv)
消费结果如下:
总结
本文简述了kafka的一些基本概念,并展示了如何用python简单的操作kafka实现消息队列模型。