持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
Kafka
在介绍kafka前首先描述几个用到的专有名词:
- Broker kafka集群的一个或者多个服务器,每个服务器或者服务提供方称之为broker
- Topic 存储的消息类别 用户只关心topic,无需关注其存储位置
- Partition 每个topic包含一个或者多个Partition
- Producer 生产者负责发布消息到Kafka
- Consumer 消费者负责读取对应Topic的消息
首先kafk并非一个数据库,而是一个分布式的流平台,这就意味着其核心存在并不是用于存储数据,而是消息(数据)的发布和订阅。因此对于kafka的定义是一个由Scala和java编写的具有高吞吐量的分布式发布订阅消息系统。
因此核心是消息队列,之前比较喜欢的一个比喻是,kafka类似于快递自提柜,对于生产者【快递员】,不需要考虑消费者【取件人】的时间,只需要把快递放到自提柜,而消费者只需要去自提货拿自己想取的快递,不需要考虑快递员的送货时间。 这样的好处就是,对于消息发送方和接收方,处理步调不一致的时候,就可以通过kafka这个中间件进行“缓冲”。如生产者是syslog实时日志外送,而消费者是每天定时处理前一天的数据,这种情况下,实时日志外送就不太适合直接与处理程序对接,而是需要kafka进行数据缓冲。
生产者
负责向某个topic上发布消息,可以选择向哪个数据分区上发布消息,一个topic可以通过多个partition进行存储,由下图所示:
多个partition可以提高队列的吞吐量,而多个broker保存着多个相同的partition组作为冗余备份,生产者只需要将数据丢到对应的partition中,至于数据的负载均衡就交给kafka完成。
消费者
kafka集群保持所有的数据,直到数据过期,而消费者并不是消费数据后删除,而是消费后读取的offset线性增加,如下图:
当正常消费数据的时候,对于每一个消费者,offset也想增加,也可通过改变offset获取之前的数据。
部署集群
由于项目需要,需要搭建kakfa集群,在此记录一下:
下载kafka的tar包:
或者直接使用:
downloads.apache.org/kafka/3.3.1…
SFTP上传至服务器,并分发至不同服务器
解压缩文件
tar -xzf kafka_2.13-3.3.1.tgz
进入文件夹:
cd kafka_2.13-3.3.1/
zookeeper
kakfa服务用到了zookeeper,因此先启动zookeeper,bin目录下的zookeeper-server-start.sh
进入bin目录执行
./zookeeper-server-start.sh ../config/zookeeper.properties
确认zookeeper 正常运行
netstat -ntlp | grep 2181
配置kafka
cd ../config/
vi server.properties
配置文件如下:
server-1
broker.id=0
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/tmp/kafka-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.retention.check.interval.ms=300000
zookeeper.connect=172.16.0.xx:2181,172.16.0.xx:2181,172.16.0.xx:2181
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0
host.name=172.16.0.xx
server-2
broker.id=1
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/tmp/kafka-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.retention.check.interval.ms=300000
zookeeper.connect=172.16.0.xx:2181,172.16.0.xx:2181,172.16.0.xx:2181
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0
host.name=172.16.0.xx
server-3
broker.id=2
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/tmp/kafka-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.retention.check.interval.ms=300000
zookeeper.connect=172.16.0.xx:2181,172.16.0.xx:2181,172.16.0.xx:2181
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0
host.name=172.16.0.xx
启动kafka
进入bin目录
./kafka-server-start.sh ../config/server.properties
Bug
【Bug】
ERROR Exiting Kafka due to fatal exception during startup. (kafka.Kafka$)
kafka.common.InconsistentClusterIdException: The Cluster ID 0WDLRbBNQnOd_ejJeDV8iw doesn't match stored clusterId Some(hwuDBpOrQWW54gFXhZnS-w) in meta.properties. The broker is trying to join the wrong cluster. Configured zookeeper.connect may be wrong.
【Solution】
从根目录启动
bin/kafka-server-start.sh config/server.properties
【Bug】
The Cluster ID kVSgfurUQFGGpHMTBqBPiw doesn't match stored clusterId Some(0Qftv9yBTAmf2iDPSlIk7g) in meta.properties. The broker is trying to join the wrong cluster. Configured zookeeper.connect may be wrong.
【Solution】
从根目录启动
删除log.dirs=/tmp/kafka-logs下的所有文件
测试
使用python编写测试脚本
producer.py
from kafka import KafkaProducer
import json
producer = KafkaProducer(
value_serializer=lambda v: json.dumps(v).encode('utf-8'),
bootstrap_servers=['threat01:9092','threat02:9092','threat03:9092']
)
def testProduct(i):
msg_dict = {
"username":f"testUser_{i}",
"userId":f"test_{i}"
}
producer.send("test", msg_dict)
producer.close()
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
print_hi('PyCharm')
for i in range(100):
testProduct(i)
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
consumer.py
# -*- coding: utf-8 -*-
from kafka import KafkaConsumer
consumer = KafkaConsumer('test', bootstrap_servers=['threat01:9092','threat02:9092','threat03:9092'])
for msg in consumer:
print(msg.value)
生产侧:
消费侧:
然后就可以愉快的使用了~ Thanks♪(・ω・)ノ