常用消息系统对比:
■ RabbitMQ
:Erlang编写,支持多协议AMQP、XMPP、SMTP、STOMP。支持负载均衡、数据持久化。同时支持Peer-to-Peer和发布/订阅模式。.
■ Redis
:基于Key-Value对的NoSQL数据库,同时支持MQ功能,可做轻量级队列服务使用。就入队操作而言,Redis对短消息(小于10KB)的性能RabbitMQ好,长消息的性能比RabbitMQ差。
■ ZeroMQ
:轻量级,不需要单独的消息服务器或中间件,应用程序本身扮演该角色,Peer-to-Peer。它实质上是一个库,需要开发人员自己组合多种技术,使用复杂度高。
■ ActiveMQ
:JMS实现,Peer-to-Peer,支持持久化.、XA事务。
■ Kafka/Jafka
:高性能跨语言的分布式发布/订阅消息系统,数据持久化,全分布式,同时支持在线和离线处理。
■ MetaQ/RocketMQ
:纯Java实现,发布/订阅消息系统,支持本地事务和XA分布式事务。
消息系统适用场景:
■ 解耦: 各位系统之间通过消息系统这个统一的接口交换数据,无须了解彼此的存在
■ 冗余: 部分消息系统具有消息持久化能力,可规避消息处理前丢失的风险
■ 扩展: 消息系统是统一的数据接口,各系统可独立扩展
■ 峰值处理能力: 消息系统可顶住峰值流量,业务系统可根据处理能力从消息系统中获取并处理对应量的请求
■ 可恢复性: 系统中部分组件失效并不会影响整个系统,它恢复后仍然可从消息系统中获取并处理数据
■ 异步通信: 在不需要立即处理请求的场景下,可以将请求放入消息系统,合适的时候再处理
Kafka
是一个高吞吐量、 持久性的分布式发布/订阅消息系统。 其有以下特点。
● 高吞吐量:单机可支持每秒100万条消息的读写。
● 消息持久化:所有消息均被持久化到磁盘,无消息丢失,支持消息重放。
● 完全分布式:Producer、Broker、Consummer均支持水平扩展。
Kafka 的数据是存储在磁盘中的, 为什么可以满足每秒百万级别消息的生产和消费? 主要是因为 Kafka 用到了磁盘顺序,所以其读写速度超过内存随机(往硬盘的)读写速度。
Kafka主要应用在实时数据计算领域。 利用Flume实时采集日志文件中的新增数据, 然后将其存储到Kafka中, 最后在Kafka 后对接实时计算程序。 这其实是一个典型的实时数据计算流程。
Kafka 中包含 Broker、Topic、Partition、Message、Producer和Consumer等组件
● Broker
: 消息的代理。 Kafka 集群中的节点(机器) 被称为 Broker。
● Topic
: 主题。 这是一个逻辑概念, 负责存储 Kafka 中的数据, 相同类型的数据一般会存储到同一个 Topic 中。 可以把 Topic 认为是数据库中的表。
● Partition
: Topic 物理上的分组。 1 个 Topic 在 Broker 中被分为 1 个或者多个 Partition。分区是在创建 Topic 时指定的, 每个 Topic 都是有分区的, 至少 1 个。 Kafka 中的数据实际上存储在 Partition 中。
● Message
: 消息, 是数据通信的基本单位。 每个消息都属于 1 个 Partition。
● Producer
: 消息和数据的生产者, 向 Kafka 的 Topic 生产数据。
● Consumer
: 消息和数据的消费者, 从 Kafka 的 Topic 消费数据。
Zookeeper 并不属于 Kafka 的组件, 但是 Kafka 可以根据需求选择依赖 Zookeeper。自Kafka 2.8版本开始,它“抛弃”了Zookeeper,引入了KIP-500架构升级,使用Raft协议实现去中心化。在新的架构中,每个Controller节点都保存所有元数据,通过KRaft协议保证副本的一致性,从而解决了Zookeeper带来的复杂度增加、必须具备Zookeeper运维能力、Controller故障处理麻烦、分区瓶颈等问题8。因此,Kafka并不再是必须依赖Zookeeper。
使用第三方开源zookeeper产品:
大数据系列 | Zookeeper架构分析及应用
官方地址:https://kafka.apache.org/downloads
kafka1安装:
root@Agent1:~# tar xf /opt/kafka_2.13-3.7.0.tgz -C /root
root@Agent1:~# cd kafka_2.13-3.7.0/config/
root@Agent1:~/kafka_2.13-3.7.0/config# vim server.properties
修改Kafka的配置文件:
主要修改server.properties
配置文件中的broker.id
、 log.dirs
和zookeeper.connect
参数
broker.id=0
log.dirs=/data/kafka-logs
#zookeeper.connect=localhost:2181
zookeeper.connect=Agent1:2181,Agent2:2181,Agent2:2181
root@Agent1:~# mkdir -p /data/kafka-logs
● broker.id
:Kafka集群中Broker的编号, 默认是从0开始的, 所以Agent1主机中的broker.id 值为 0。
● log.dirs
: Kafka 中的数据存储目录。 建议指定到存储空间比较大的磁盘中, 因为在实际工作中 Kafka 中会存储很多数据。
● zookeeper.connect
: Zookeeper 集群的地址, 多个地址之间使用逗号分隔。
root@Agent1:~/kafka_2.13-3.7.0# bin/kafka-server-start.sh -daemon config/server.properties
root@Agent1:~/kafka_2.13-3.7.0# jps
160227 Jps
159628 QuorumPeerMain
160141 Kafka
同样的方式安装Agent2和Agent3主机,并修改broker.id
参数的值
kafka2安装:
root@Agent2:~/kafka_2.13-3.7.0/config# vim server.properties
broker.id=1
log.dirs=/data/kafka-logs
zookeeper.connect=Agent1:2181,Agent2:2181,Agent2:2181
root@Agent2:~/kafka_2.13-3.7.0# bin/kafka-server-start.sh -daemon config/server.properties
root@Agent2:~/kafka_2.13-3.7.0# jps
154018 Kafka
153505 QuorumPeerMain
154070 Jps
kafka3安装:
root@Agent3:~/kafka_2.13-3.7.0/config# vim server.properties
broker.id=2
log.dirs=/data/kafka-logs
zookeeper.connect=Agent1:2181,Agent2:2181,Agent2:2181
root@Agent3:~/kafka_2.13-3.7.0# bin/kafka-server-start.sh -daemon config/server.properties
root@Agent3:~/kafka_2.13-3.7.0# jps
162163 Jps
162116 Kafka
161589 QuorumPeerMain
启动Kafka集群:
root@Agent1:~/kafka_2.13-3.7.0# bin/kafka-server-start.sh -daemon config/server.properties
root@Agent2:~/kafka_2.13-3.7.0# bin/kafka-server-start.sh -daemon config/server.properties
root@Agent3:~/kafka_2.13-3.7.0# bin/kafka-server-start.sh -daemon config/server.properties
验证Kafka集群的运行状态:
分别在Agent1、 Agent2和Agent3上执行jps
命令验证是否有Kafka进程, 如果都有则说明Kafka集群启动成功了, 否则需要到对应的机器上查看 Kafka 的日志信息
root@Agent1:~/kafka_2.13-3.7.0# jps
924314 Jps
507311 QuorumPeerMain
160799 Kafka
169837 Application
配置kafka命令的环境变量:
# vim /etc/profile
# kafka
export KAFKA_HOME=/opt/kafka_2.13-3.0.0
export PATH=$PATH:$KAFKA_HOME/bin
# source /etc/profile
# cat /lib/systemd/system/kafka.service
[Unit]
Description=Apache Kafka Server
After=network.target remote-fs.target kafka-zookeeper.service
[Service]
Type=forking
User=root
Group=root
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/java/jdk1.8/bin:/opt/zookeeper-3.4.6/bin:/root/bin"
ExecStart=/opt/kafka_2.13-3.0.0/bin/kafka-server-start.sh -daemon /opt/kafka_2.13-3.0.0/config/server.properties
ExecStop=/opt/kafka_2.13-3.0.0/bin/kafka-server-stop.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
# chmod a+x kafka.service
Environment此配置必须配置,否则会导致kafka启动失败
# systemctl daemon-reload
# systemctl start kafka
# systemctl status kafka.service
● kafka.service - Apache Kafka Server
Loaded: loaded (/usr/lib/systemd/system/kafka.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2024-08-20 13:58:55 CST; 4s ago
Process: 2744 ExecStart=/opt/kafka_2.13-3.0.0/bin/kafka-server-start.sh -daemon /opt/kafka_2.13-3.0.0/config/server.properties (code=exited, status=0/SUCCESS)
Main PID: 3092 (java)
Tasks: 61
Memory: 301.3M
CGroup: /system.slice/kafka.service
└─3092 java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -...
Aug 20 13:58:55 dn01 systemd[1]: Starting Apache Kafka Server...
Aug 20 13:58:55 dn01 systemd[1]: Started Apache Kafka Server.
创建Topic:
在安装好Kafka集群之后, 还需要先在Kafka中创建Topic, 之后就可以基于 Kafka 生产和消费数据了。
root@Agent3:~/kafka_2.13-3.7.0# bin/kafka-topics.sh --create --topic hello --partitions 5 --replication-factor 2 --bootstrap-server localhost:9092
Created topic hello.
● --create
: 创建 Topic。
● --zookeeper
: 指定Kafka集群使用的Zookeeper集群地址, 指定1个或者多个都可以, 多个用逗号分隔。
● --partitions
: 指定Topic中的分区数量。
● --replication-factor
: 指定Topic中分区的副本因子, 这个参数的值需要小于或等于Kafka集群中Broker的数量。
● --topic
: 指定Topic的名称
root@Agent3:~/kafka_2.13-3.7.0# bin/kafka-topics.sh --describe --topic hello --bootstrap-server localhost:9092
Topic: hello TopicId: wvzIUg03RN6FMc9iA4-QNw PartitionCount: 5 ReplicationFactor: 2 Configs:
Topic: hello Partition: 0 Leader: 0 Replicas: 0,1 Isr: 0,1
Topic: hello Partition: 1 Leader: 2 Replicas: 2,0 Isr: 2,0
Topic: hello Partition: 2 Leader: 1 Replicas: 1,2 Isr: 1,2
Topic: hello Partition: 3 Leader: 0 Replicas: 0,2 Isr: 0,2
Topic: hello Partition: 4 Leader: 2 Replicas: 2,1 Isr: 2,1
启动基于控制台的生产者并向指定 Topic 中生产数据:
Kafka 默认提供了基于控制台的生产者 , 直接使用Kafka的bin目录下的kafka-console-producer.sh
即可, 方便测试
启动基于控制台的生产者之后, 生产测试数据: hehe
root@Agent3:~/kafka_2.13-3.7.0# bin/kafka-console-producer.sh --topic hello --bootstrap-server localhost:9092
>hehe
>
● broker-list
: 指定Kafka集群的地址, 指定1个或者多个都可以, 指定多个时用逗号隔开。
● topic
: 指定要生产数据的Topic名称
kafka默认提供了基于控制台的消费者, 直接使用Kafka 的 bin目录下的kafka-consoleconsumer.sh
即可, 方便测试。
root@Agent1:~# cd kafka_2.13-3.7.0/
root@Agent1:~/kafka_2.13-3.7.0# bin/kafka-console-consumer.sh --topic hello --from-beginning --bootstrap-server localhost:9092
hehe
● bootstrap-server
: 指定Kafka集群的地址, 指定1个或者多个都可以, 指定多个时用逗号分隔。
● topic
: 指定要消费数据的Topic名称
● --from-beginning
:Kafka消费者默认是消费最新生产的数据, 如果想消费之前生产的数据, 则需要添加参数–from-beginning, 表示从头消费。
Kafka的生产者和消费者也可以使用Java代码来实现。 不过在实际工作中并不会经常这么用, 因为和 Kafka 经常对接使用的技术框架(例如 Flume) 已经内置了对应的消费者和生产者代码, 在使用时只需要进行简单的配置即可。
kafka和zookeeper对接成功之后,可以在zookeeper中查看kafka的信息:
[zk: localhost:2181(CONNECTED) 5] ls /brokers
[ids, seqid, topics]
[zk: localhost:2181(CONNECTED) 1] ls /brokers/ids
[0, 1, 2]
[zk: localhost:2181(CONNECTED) 2] get /brokers/ids/0
{"features":{},"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://Agent1:9092"],"jmx_port":-1,"port":9092,"host":"Agent1","version":5,"timestamp":"1711374513109"}
kafka控制器的作用是在Zookeeper的帮助下管理和协调整个Kafka集群,任意一台Broker可以成为Controller,但是只有一台会Controller
leader和控制器可以不是同一台机器。ZooKeeper集群中会有一个选举过程来决定哪台服务器作为Leader,这个选举是基于ZooKeeper的内部机制进行的。一旦选举完成,Leader就负责处理所有的客户端请求,并确保集群中的其他服务器(被称为Follower)与它保持同步。
控制器负责维护集群的元数据信息,处理客户端的创建、删除节点等操作,并将这些操作同步到其他服务器上。因此,控制器和Leader虽然有所区别,但在实践中,控制器通常是Leader,因为Leader负责处理所有客户端请求。但理论上,它们可以在不同的服务器上。
控制器的选取:
Broker启动时,会尝试创建ZK中 /controller znode,第一个创建/controller的Broker会是Controller
[zk: localhost:2181(CONNECTED) 2] get /controller
{"version":2,"brokerid":1,"timestamp":"1711374505881","kraftControllerEpoch":-1}
控制器的功能:
● topic
管理:当使用kafka-topics脚本时,后台工作通过 controller 完成
● 分区重分配:对已有 topic 分区进行细粒度的分配
● Preferred Leader 选举:Kafka为了避免部分Broker负载过重而提供的一种换Leader的方案
● 集群成员管理(新增 Broker、Broker 主动关闭、Broker 宕机):自动检测 Broker、controller 通过 watch 机制检查 ZK 的 /brokers/ids 子节点数量变更
● 数据服务:controller向其他Broker提供数据服务、controller上保存了最全的集群元数据
控制器故障转移Failover:
Controller存在单点
故障转移:当运行中的Controller突然宕机,Kafka能够快速感知,并立即启用备用Controller代替之前失败的Controller,这个过程称为 Failover