Kafka最初于2011年在 LinkedIn 开发,自那时起经历了很多改进,后来捐献给Apache基金,如今发展成为一个完整的平台,采用Scala和Java开发的开源流处理软件。
Kafka 是我工作多年使用最多的消息中间件 ,特点是拥有巨大吞吐量(数百万/秒),作为当下最流行的分布式,可水平扩展,可容错的“消息系统”。
2020年,Kafka 依旧炙手可热,一线大公司即使不用Kafka,但是自研产品也都是基于Kafka,或者完全借鉴Kafka设计思想,理论上来说,如果你还没熟练掌握一个MQ框架,Kafka绝对是不错的选择。
构建一个 Kafka cluster 首先需要理解 topics, producers, consumers, and brokers 的概念,弄懂这几个概念才能更好地了解Kafka的工作机制。
Producer:消息的生产方,如支付系统确认用户已经支付,支付系统要通知订单系统和物流系统,支付系统就是生产者。
Consumer:消费的接收方,Producer 的案例中,物流系统就是消费方,前两个都比较简单,我就不多说了。
Topic:每条发布到MQ集群的消息都有一个类别,这个类别被称为topic,可以理解成一类消息的名字。所有的消息都已topic作为单位进行归类。
Partition:Kafka 物理上分区的概念,每个 Topic 会分散在一个或多个 Partition。一个 Topic 的数据太大了,就分成小片,Kafka 为分区引入多副本模型,副本之间采用“一个leader多follower”的设计,通过多副本实现故障自动转移,保证可用性。
Broker:可以理解成一个服务器的节点,集群包含一个或多个服务器,这种服务器被称为 broker。对应用来说,生产者把消费发出去了,就不管了。消费者慢条斯理地按照自己的速率来消费。这段时间可能有大量消息产生,消费者压力还是在一定范围内。做生产者和消费者之间解耦的就是一个缓存服务broker。
Kafka Cluster:集群就是 Broker 的集合,多个 Broker 组成一个高可用集群。
Producer 与 Consumer的关系
topic 和 Partition 的关系
一个 topic 可以分别存储到多个 Partition,每个 Partition 有序的。
Kafka 特有的功能:
1、相比同类中间件 RabbitMQ or ActiveMQ,Kafka 支持批量拉取消息,大大增加了Kafka的消息吞吐量。
2、支持多种发送场景:
1)发送并忘记。
2)同步发送 。
3)异步发送+回调函数。
3种方式虽然在时间上有所差别,但并不是说时间越快的越好,具体使用哪种方式要看具体的业务场景,比如业务要求消息必须是按顺序发送,可以使用第2种同步发送,并且只能在一个partation上。如果业务只关心消息的吞吐量,容许少量消息发送失败,也不关注消息的发送顺序,那么可以使用发送并忘记的方式。如果业务需要知道消息发送是否成功,并且对消息的顺序不关心,那么可以用异步+回调的方式来发送消息
3、分布式可高可扩展。Kafka 集群可以透明的扩展,增加新的服务器进集群。
只说了 Kafka 的优势,那别的同类产品就不好了吗?当然不是,存在即真理,每个产品能生存下来,一定有它自己的优势,比如 RabbitMQ,在吞吐量方面稍逊于 Kafka ,但是他们的出发点不一样,RabbitMQ 支持对消息的可靠的传递,支持事务,不支持批量的操作,技术选型中,选择最适合你的,你最了解熟悉的。
kafka优势总结 :
分布式 高性能 持久性和扩展性
支持多分区 高吞吐量 数据可持久化
支持多副本 低延迟 容错性高
支持多订阅者 高并发 支持水平在线扩展
基于ZooKeeper调度 时间复杂度为O(1) 消息分发自动平衡
百度 :安装 kafka 安装,出来一堆的教程,
1)Kafka安装教程
2)kafka入门、安装详解
3) kafka 安装部署教程
总结 :手动安装大致过程 :官网下载二进制文件,需要修改配置文件,手动启动并停止,
过程感受 :设置的步骤很多,对机器的依赖比较大,过程较为繁琐,也能走得通,配置集群时就会有设置步骤较多
百度:基于docker安装 kafka 安装,找到几个较为好的教程
1)基于docker搭建kafka
2)
步骤1:拉取镜像
在docker上安装kafka需要先安装zookeeper,我们可以使用docker pull先把zookeeper和kafka的镜像拉取下来
docker pull zookeeper
docker pull bitnami/kafka
步骤2:运行zookeeper
docker run -d --name zookeeper -p 2181:2181 -t registry.test.com/library/zookeeper
步骤3:运行kafka
docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=0 -e KAFKA_ZOOKEEPER_CONNECT=10.10.0.0:2181 -e ALLOW_PLAINTEXT_LISTENER=yes -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://10.10.0.0:9092 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -t bitnami/kafka
步骤4:创建topic
# 查询kafka容器ID
docker ps |grep kafka
# 进入kafka容器
docker exec -it 53cc0e000953 /bin/bash
# 创建topic mykafkadk
/opt/kafka/bin/kafka-topics.sh --zookeeper 10.160.32.28:2181 --create --replication-factor 1 --partitions 1 --topic mykafkadk
步骤5:创建生产者和消费者
cd /opt/kafka
./bin/kafka-console-producer.sh --broker-list 192.168.1.111:9092 --topic test
./bin/kafka-console-consumer.sh --bootstrap-server 192.168.1.111:9092 --topic test --from-beginning
示例:
运行安装第二个kafka时需要修改如下参数:
1) name
2)端口号
3)KAFKA_BROKER_ID
docker run -d --name kafka1 -p 9093:9093 -e KAFKA_BROKER_ID=2 -e KAFKA_ZOOKEEPER_CONNECT=10.10.0.0:2181 -e ALLOW_PLAINTEXT_LISTENER=yes KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://10.10.0.0:9093 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9093 -t bitnami/kafka
创建两个kafka公用的topic:
/opt/kafka/bin/kafka-console-producer.sh --broker-list 10.160.32.28:9093 --topic kafkatesttopic1
发送消息:
/opt/kafka/bin/kafka-console-producer.sh --broker-list 10.160.32.28:9093 --topic kafkatesttopic1
消费消息 :
/opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server 10.160.32.28:9093 --topic kafkatesttopic1 --from-beginning
1.文件目录
-根目录
-dockerData 目录
-kafka-jiqun 目录
-docker-compose.yaml 集群启动配置文件
-start.sh 启动器
-stop.sh 停止删除器
2.编辑文件docker-compose.yaml 根据你的情况进行修改 主要是-目录-ip-端口
针对一个zookeeper情况:
*********************************************************************************
version: "3"
services:
zookeeper:
image: zookeeper
build:
context: ./
container_name: zookeeper-jiqun
ports:
- 2182:2181
volumes:
- /dockerData/kafka-jiqun/zookeeper/data:/data
- /dockerData/kafka-jiqun/zookeeper/datalog:/datalog
- /dockerData/kafka-jiqun/zookeeper/logs:/logs
restart: always
kafka_node_0:
depends_on:
- zookeeper
build:
context: ./
container_name: kafka-node-0
image: wurstmeister/kafka
environment:
KAFKA_BROKER_ID: 0
KAFKA_ZOOKEEPER_CONNECT: 192.168.19.132:2182
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.19.132:9093
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9093
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
ports:
- 9093:9093
volumes:
- /dockerData/kafka-jiqun/kafka/node_0:/kafka
restart: unless-stopped
kafka_node_1:
depends_on:
- kafka_node_0
build:
context: ./
container_name: kafka-node-1
image: wurstmeister/kafka
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 192.168.19.132:2182
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.19.132:9094
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9094
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
ports:
- 9094:9094
volumes:
- /dockerData/kafka-jiqun/kafka/node_1:/kafka
restart: unless-stopped
kafka_node_2:
depends_on:
- kafka_node_1
build:
context: ./
container_name: kafka-node-2
image: wurstmeister/kafka
environment:
KAFKA_BROKER_ID: 2
KAFKA_ZOOKEEPER_CONNECT: 192.168.19.132:2182
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.19.132:9095
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9095
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
ports:
- 9095:9095
volumes:
- /dockerData/kafka-jiqun/kafka/node_2:/kafka
restart: unless-stopped
*********************************************************************************
针对多个zookeeper:
*********************************************************************************
version: "3"
services:
zookeeper-node-0:
image: zookeeper
build:
context: ./
container_name: zookeeper-node-0
ports:
- 2182:2181
volumes:
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-0/data:/data
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-0/datalog:/datalog
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-0/logs:/logs
restart: always
zookeeper-node-1:
image: zookeeper
build:
context: ./
container_name: zookeeper-node-1
ports:
- 2183:2181
volumes:
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-1/data:/data
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-1/datalog:/datalog
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-1/logs:/logs
restart: always
zookeeper-node-2:
image: zookeeper
build:
context: ./
container_name: zookeeper-node-2
ports:
- 2184:2181
volumes:
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-2/data:/data
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-2/datalog:/datalog
- /dockerData/kafka-jiqun/zookeeper/zookeeper-node-2/logs:/logs
restart: always
kafka_node_0:
depends_on:
- zookeeper-node-0
- zookeeper-node-1
- zookeeper-node-2
build:
context: ./
container_name: kafka-node-0
image: wurstmeister/kafka
environment:
KAFKA_BROKER_ID: 0
KAFKA_ZOOKEEPER_CONNECT: 192.168.19.132:2182,192.168.19.132:2183,192.168.19.132:2184
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.19.132:9093
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9093
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
ports:
- 9093:9093
volumes:
- /dockerData/kafka-jiqun/kafka/node_0:/kafka
restart: unless-stopped
kafka_node_1:
depends_on:
- kafka_node_0
build:
context: ./
container_name: kafka-node-1
image: wurstmeister/kafka
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 192.168.19.132:2182,192.168.19.132:2183,192.168.19.132:2184
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.19.132:9094
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9094
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
ports:
- 9094:9094
volumes:
- /dockerData/kafka-jiqun/kafka/node_1:/kafka
restart: unless-stopped
kafka_node_2:
depends_on:
- kafka_node_1
build:
context: ./
container_name: kafka-node-2
image: wurstmeister/kafka
environment:
KAFKA_BROKER_ID: 2
KAFKA_ZOOKEEPER_CONNECT: 192.168.19.132:2182,192.168.19.132:2183,192.168.19.132:2184
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.19.132:9095
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9095
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
ports:
- 9095:9095
volumes:
- /dockerData/kafka-jiqun/kafka/node_2:/kafka
restart: unless-stopped
*********************************************************************************
3.编辑start.sh启动器 这个不谢也没事就是不断的得写里面的命令
#! /bin/bash
sudo docker-compose up -d
4.编辑stop.sh停止-移除器 这个不谢也没事就是不断的得写里面的命令
针对一个zookeeper的情况:
***************************************************
#!/bin/bash
sudo docker stop kafka-node-0
sudo docker stop kafka-node-1
sudo docker stop kafka-node-2
sudo docker stop zookeeper-jiqun
sudo docker rm -f kafka-node-0
sudo docker rm -f kafka-node-1
sudo docker rm -f kafka-node-2
sudo docker rm -f zookeeper-jiqun
***************************************************
针对多个zookeeper的情况:
***************************************************
#!/bin/bash
sudo docker stop kafka-node-0
sudo docker stop kafka-node-1
sudo docker stop kafka-node-2
sudo docker stop zookeeper-node-0
sudo docker stop zookeeper-node-1
sudo docker stop zookeeper-node-2
sudo docker rm -f kafka-node-0
sudo docker rm -f kafka-node-1
sudo docker rm -f kafka-node-2
sudo docker rm -f zookeeper-node-0
sudo docker rm -f zookeeper-node-1
sudo docker rm -f zookeeper-node-2
***************************************************
5.检查docker-componse 是否存在
命令:
sudo docker-compose --version
如果没有进行以下操作
安装docker-componse:
sudo wget https://github.com/docker/compose/releases/download/1.23.0-rc3/docker-compose-Linux-x86_64
移动:
sudo mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
授权:
sudo chmod +x /usr/local/bin/docker-compose
执行:
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
验证:
sudo docker-compose --version
6.上述没有问题 启动集群
命令:
sudo bash start.sh
7.上述没有问题 停止集群
命令:
sudo bash stop.sh
Python 接 Kafka 的标准库,kafka-python 和 pykafka。kafka-python 使用的人多是比较成熟的库,kafka-python 并没有zk的支持。pykafka 是 Samsa 的升级版本,使用 samsa 连接zookeeper,生产者直接连接 kafka 服务器列表,消费者才用zookeeper。