目录
[consumer group](#consumer group)
假设一个程序员在维护两个服务器,一个是A另一个是B,A每秒发出200个消息,B每秒只能处理100个消息,此时B是接收不过来的,常规情况下要么"开源"要么"节流",减少A发出的消息数量,或者增加B的处理速度,最简单直接的就是再增设一台C服务器用来帮助B进行负载均衡,但这样做成本太高,有什么办法可以让B独自处理来自A的消息而且不会导致自身因为超出负荷而瘫痪呢?
没有什么是增加中间层解决不了的,我们在两个服务器之间添加一个消息队列,A发送的消息首先进入消息队列,然后由消息队列发送至B服务器,常用的消息队列就是Kafka
Kafka是什么
Kafka就是一个消息队列,所以如果问kafka是什么,就相当于问消息队列是什么,消息队列就是通过将消息放在内存中的队列中,可以保护消息不被丢失。但是,这会带来性能问题,因此可以将队列挪到一个单独的进程中,从而解决性能问题。此外,还可以通过分区、分片、添加副本来扩展消息队列,提高性能和可用性。
Kafka的特性
高吞吐量、低延迟
可扩展性,kafka集群支持热扩展
持久化、可靠性,消息呗持久化到本地磁盘,并且支持数据备份防止数据丢失
容错性,允许集群中的某个或某系节点下线的情况存在
高并发,支持数千个客户端同时读写
Kafka系统架构
Kafka通过将消息放入队列中,减轻了消息处理端的负载,将消息放入消息队列的一端称为生产者,处理消息的一段称为消费者。但是话又说回来,消息队列说到底也只是一个缓冲区,只能作为缓兵之计,如果生产的消息在很长一段时间甚至几年内都处于居高不下的状态,那该花钱还是得花钱,为了提升性能和扩展性,可以增加消费者和生产者的数量,并通过分区和副本来保证高可用性。
topic
随着生产者和消费者的增多,慢慢的消息队列开始变得拥堵,就会出现多个生产者或消费者争抢一个消息队列的情况,这时候该如何做呢?面多加水,水多加面呗,我们再增加一条消息队列不就可以了?不多再多增一条未免有些麻烦了,在消息队列内部就直接进行分类,每一类是一个topic,然后根据topic新增队列的数量, 生产者根据 topic 主题的不同,将消息投递到不同的队列中,消费者根据订阅的消息的类型,从相应的队列中读取消息。
partition
每个topic代表不同类型或主题的消息,自然有多有少,像系统进程允许之类的日志,消息是非常多的,就导致这个topic 处理的请求也过多,来不及处理,此时可将 topic 拆分成好几段,每段就是一个partition分区,每个消费者负责一个partition,这样每个消费者负责一个partition分区,大大降低了消息队列堵塞的可能性
每个 partition 有多个副本(Replica),其中有且仅有一个作为 Leader,Leader 是当前负责数据的读写的 partition。Follower 跟随 Leader,所有写请求都通过 Leader 路由,数据变更会广播给所有 Follower, Follower 与 Leader 保持数据同步。Follower 只负责备份,不负责数据的读写。 如果 Leader 故障,则从 Follower 中选举出一个新的 Leader。 当 Follower 挂掉、卡住或者同步太慢,Leader 会把这个 Follower 从 ISR(Leader 维护的一个和 Leader 保持同步的 Follower 集合) 列表中删除,重新创建一个 Follower。
broker
当然,如此多的partition分布在一台机器上,肯定会造成机器负载,将partition分布在不同的机器上,可以大大减少这方面问题,每台机器就是一个broker,一个broker 中有多个topic,每个topic被划分为不同的partition
当 broker 存储 topic 的数据时,如果某 topic 有 N 个 partition,集群有 N 个 broker,那么每个 broker 存储该 topic 的一个 partition;如果某 topic 有 N 个 partition,集群有 (N+M) 个 broker,那么其中有 N 个 broker 存储 topic 的 一个 partition, 剩下的 M 个 broker 不存储该 topic 的 partition 数据;如果某 topic 有 N 个 partition,集群中 broker 数目少于 N 个,那么一个 broker 存储该 topic 的 一个或多个 partition,实际情况中,避免broker数少于partition,这种情况容易导致 Kafka 集群数据不均衡
consumer group
消费者组,由多个 consumer 组成,消费者组内的消费者共同消费一个或多个topic,消费者组之间互不干扰
offset
消息队列如是工作,假如有一天broker挂了,那岂不是数据全部都丢失了?所以,不能仅仅将数据放在内存中,还要将其持久化到磁盘中,这样数据的安全性便有了保障,但是新的问题出现了,如果broker挂了,之后进行了数据恢复,消费者再次去拉取消息,应该从何处开始。这里就引入了一个新的概念 offset(偏移量),记录消费者读取数据的位置,以便下次直接读取。当然,还有一个问题,这样一直持久化下去,磁盘空间会越来越少,所以要对这部分持久化的数据进行定期清理,默认周期时 7*24小时
zookeeper
到这里,整个体系已经由原来的AB两台机器中间的消息队列,扩展到相当多的组件了,而且每个组件都有自己的数据和状态,所以,就需要有一个组件来统一维护和管理这些组件的状态信息,zookeeper就是扮演着这个角色,掌握kafka的状态信息
部署安装kafka
在官网中下载kafka压缩包或者安装包 放在/opt下
cd /opt
tar zxvf kafka_2.13-2.7.1.tgz
mv kafka_2.13-2.7.1 /usr/local/kafka
cd /usr/local/kafka/config/
将配置文件备份
cp server.properties{,.bak}
vim server.properties
broker.id=0 #21行,broker的全局唯一编号,不重复,因此其他机器上不能为0
listeners=PLAINTEXT://172.16.233.105:9092 #31行,指定坚挺的ip和端口号
num.network.threads=3 #42行,broker 处理网络请求的线程数量
num.io.threads=8 #45行,用来处理磁盘IO的线程数量,数值应该大于硬盘数
socket.send.buffer.bytes=102400 #48行,发送套接字的缓冲区大小
socket.receive.buffer.bytes=102400 #51行,接收套接字的缓冲区大小
socket.request.max.bytes=104857600 #54行,请求套接字的缓冲区大小
log.dirs=/usr/local/kafka/logs #60行,kafka运行日志存放的路径,也是数据存放的路径
num.partitions=1 #65行,topic在当前broker上的默认分区数,topic创建时指定参数会覆盖
num.recovery.threads.per.data.dir=1 #69行,用来恢复和清理data下数据的线程数量
log.retention.hours=168 #103行,segment 文件保留的最长时间,单位h,默认7天删除
log.segment.bytes=1073741824 #110行,一个segment文件最大的大小,默认为1G
zookeeper.connect=172.16.233.105:2181,172.16.233.106:2181,172.16.233.107:2181
#123行,配置连接zookeeper集群地址
保存退出
修改环境变量
vim /etc/profile
export KAFKA_HOME=/usr/local/kafka
export PATH=PATH:KAFKA_HOME/bin
source /etc/profile
配置 zookeeper 启动脚本
vim /etc/init.d/kafka
#!/bin/bash
#chkconfig:2345 22 88
#description:kafka Service Control Script
KAFKA_HOME='/usr/local/kafka'
case $1 in
start)
echo "-------------- kafka 启 动 -------------------"
${KAFKA_HOME}/bin/kafka-server-start.sh -daemon
${KAFKA_HOME}/config/server.properties
;;
stop)
echo "-------------- kafka 停 止 -------------------"
${KAFKA_HOME}/bin/kafka-server-stop.sh
;;
restart)
$0 stop
$0 start
;;
status)
echo "-------------- kafka 状 态 -------------------"
count=$(ps -ef | grep kafka | egrep -cv "grep | $$")
if [ "$count" -eq 0 ];then
echo "kafka is not running"
else
echo "kafka is running"
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
esac
保存退出
赋权
chmod +x /etc/init.d/kafka
设置开机自启
chkconfig --add kafka
启动kafka
service kafka start
kafka已经安装部署完成
下面是kafka操作命令
创建topic
kafka-topics.sh --create --zookeeper
172.16.233.105:2181,172.16.233.106:2181,172.16.233.107:2181 --replication-factor 2 --partitions 3 --topic test
查看当前服务器中的所有 topic
172.16.233.105:2181,172.16.233.106:2181,172.16.233.107:2181