赞
踩
目录
1.3.1点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除)
1.3.2发布/订阅模式(一对多,又叫观察者模式,消费者消费数据之后不会清除消息)
(6)Consumer Group(CG)消费者组,由多个 consumer 组成。
当前比较常见的 MQ 中间件有 ActiveMQ、RabbitMQ、RocketMQ、Kafka 等。
当前比较常见的 MQ 中间件有 ActiveMQ、RabbitMQ、RocketMQ、Kafka 等。
雪崩:高并发情况下redis服务器无法同时处理大量请求,导致rdis崩溃直接查询数据库。
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
消息生产者生产消息发送到消息队列中,然后消息消费者从消息队列中取出并且消费消息。消息被消费以后,消息队列中不再有存储,所以消息消费者不可能消费到已经被消费的消息。消息队列支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
点对点(一对一):消费者主动拉取数据,消费者将生产者生成的数据拉取完成则消费者将消息删除
消息生产者(发布)将消息发布到 topic 中,同时有多个消息消费者(订阅)消费该消息。
和点对点方式不同,发布到 topic 的消息会被所有订阅者消费。
发布/订阅模式是定义对象间一种一对多的依赖关系,使得每当一个对象(目对标象)的状态发生改变,则所有依赖于它的对象(观察者对象)都会得到通知并自动更新。
发布/订阅模式(一对多,又叫观察者模式,消费者消费数据之后不会清除消息)
Kafka 是一个分布式的基于发布/订阅模式的消息队列(MQ,Message Queue),主要应用于大数据实时处理领域
Kafka 是最初由 Linkedin 公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于 Zookeeper 协调的分布式消息中间件系统
它的最大的特性就是可以实时的处理大量数据以满足各种需求场景,比如基于 hadoop 的批处理系统、低延迟的实时系统、Spark/Flink 流式处理引擎,nginx 访问日志,消息服务等等,
用 scala 语言编写,Linkedin 于 2010 年贡献给了 Apache 基金会并成为顶级开源项目。
Kafka 每秒可以处理几十万条消息,它的延迟最低只有几毫秒。
每个 topic 可以分多个 Partition,Consumer Group 对 Partition 进行消费操作,提高负载均衡能力和消费能力
kafka 集群支持热扩展
热扩展(数据在运行中可以不用停掉服务)
消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
允许集群中节点失败(多副本情况下,若副本数量为 n,则允许 n-1 个节点失败)
支持数千个客户端同时读写
topic:主题。每一个消息都属于某个主题,kafka通过主题来划分消息,是一个逻辑上的分类
为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服务器)上,一个 topic 可以分割为一个或多个 partition,每个 partition 是一个有序的队列
Kafka 只保证 partition 内的记录是有序的,而不保证 topic 中不同 partition 的顺序。
每个 topic 至少有一个 partition,当生产者产生数据的时候,会根据分配策略选择分区,然后将消息追加到指定的分区的队列末尾
1.指定了 patition,则直接使用;
2.未指定 patition 但指定 key(相当于消息中某个属性),通过对 key 的 value 进行 hash 取模,选出一个 patition;
3.patition 和 key 都未指定,使用轮询选出一个 patition。
每条消息都会有一个自增的编号,用于标识消息的偏移量,标识顺序从 0 开始
每个 partition 中的数据使用多个 segment 文件存储
如果 topic 有多个 partition,消费数据时就不能保证数据的顺序。严格保证消息的消费顺序的场景下(例如商品秒杀、 抢红包),需要将 partition 数目设为 1。
●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。在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致 Kafka 集群数据不均衡。
副本,为保证集群中的某个节点发生故障时,该节点上的 partition 数据不丢失,且 kafka 仍然能够继续工作,kafka 提供了副本机制,一个 topic 的每个分区都有若干个副本,一个 leader 和若干个 follower
Replica:副本,一个分区可以有多个副本来提高容灾性,一般是设置一个分区2个副本
每个 partition 有多个副本,其中有且仅有一个作为 Leader,Leader 是当前负责数据的读写的 partition
Follower 跟随 Leader,所有写请求都通过 Leader 路由,数据变更会广播给所有 Follower,Follower 与 Leader 保持数据同步。Follower 只负责备份,不负责数据的读写
如果 Leader 故障,则从 Follower 中选举出一个新的 Leader。
当 Follower 挂掉、卡住或者同步太慢,Leader 会把这个 Follower 从 ISR(Leader 维护的一个和 Leader 保持同步的 Follower 集合) 列表中删除,重新创建一个 Follower。
leader负责读写,follow只负责复制和备份
生产者即数据的发布者,该角色将消息 push 发布到 Kafka 的 topic 中。
broker 接收到生产者发送的消息后,broker 将该消息追加到当前用于追加数据的 segment 文件中。
生产者发送的消息,存储到一个 partition 中,生产者也可以指定数据存储的 partition。
生产者,也就是写入消息的一方,将消息写入broker中
消费者可以从 broker 中 pull 拉取数据。消费者可以消费多个 topic 中的数据。
消费者,也就是读取消息的一方,从broker中读取消息
所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
可为每个消费者指定组名,若不指定组名则属于默认的组。
将多个消费者集中到一起去处理某一个 Topic 的数据,可以更快的提高数据的消费能力。
消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费,防止数据被重复读取。
消费者组之间互不影响
可以唯一的标识一条消息
偏移量决定读取数据的位置,不会有线程安全的问题,消费者通过偏移量来决定下次读取的消息(即消费位置)
消息被消费之后,并不被马上删除,这样多个业务就可以重复使用 Kafka 的消息。
某一个业务也可以通过修改偏移量达到重新读取消息的目的,偏移量由用户控制。
消息最终还是会被删除的,默认生命周期为 1 周(7*24小时)
Offset:偏移量。消费者存在zookeeper上的记录自己访问到什么地方
Kafka 通过 Zookeeper 来存储集群的 meta 信息。
Zookeeper:kafka使用zookeeper来管理集群的元数据,以及控制器的选举等操作
meta:元信息
由于 consumer 在消费过程中可能会出现断电宕机等故障,consumer 恢复后,需要从故障前的位置的继续消费,所以 consumer 需要实时记录自己消费到了哪个 offset,以便故障恢复后继续消费。
Kafka 0.9 版本之前,consumer 默认将 offset 保存在 Zookeeper 中;从 0.9 版本开始,consumer 默认将 offset 保存在 Kafka 一个内置的 topic 中,该 topic 为 __consumer_offsets。
也就是说,zookeeper的作用就是,生产者push数据到kafka集群,就必须要找到kafka集群的节点在哪里,这些都是通过zookeeper去寻找的。消费者消费哪一条数据,也需要zookeeper的支持,从zookeeper获得offset,offset记录上一次消费的数据消费到哪里,这样就可以接着下一条数据进行消费
(架构在Zookeeper集群之上搭建)
主机名 ip地址 安装软件 系统版本 zk_kfk1 192.168.246.7 apache-zookeeper-3.5.7-bin.tar.gz
kafka_2.13-2.7.1.tgz
centos7 zk_kfk2 192.168.246.9 apache-zookeeper-3.5.7-bin.tar.gz
kafka_2.13-2.7.1.tgz
centos7 zk_kfk3 192.168.246.12 apache-zookeeper-3.5.7-bin.tar.gz
kafka_2.13-2.7.1.tgz
centos7
- 1.下载安装包
- 官方下载地址:http://kafka.apache.org/downloads.html
-
- cd /opt
- wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.7.1/kafka_2.13-2.7.1.tgz
-
-
- 2.安装 Kafka
- 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的全局唯一编号,每个broker不能重复,因此要在其他机器上配置 broker.id=1、broker.id=2
- listeners=PLAINTEXT://192.168.10.17:9092 ●31行,指定监听的IP和端口,如果修改每个broker的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文件(数据文件)保留的最长时间,单位为小时,默认为7天,超时将被删除
- log.segment.bytes=1073741824 #110行,一个segment文件最大的大小,默认为 1G,超出将新建一个新的segment文件
- zookeeper.connect=192.168.10.17:2181,192.168.10.21:2181,192.168.10.22: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
-
-
- 3.Kafka 命令行操作
- //创建topic
- kafka-topics.sh --create --zookeeper 192.168.10.17:2181,192.168.10.21:2181,192.168.10.22:2181 --replication-factor 2 --partitions 3 --topic test
-
- kafka-topics.sh --create --zookeeper 192.168.10.17:2181,192.168.10.20:2181,192.168.10.21:2181 --replication-factor 2 --partitions 3 --topic test
- -------------------------------------------------------------------------------------
- --zookeeper:定义 zookeeper 集群服务器地址,如果有多个 IP 地址使用逗号分割,一般使用一个 IP 即可
- --replication-factor:定义分区副本数,1 代表单副本,建议为 2
- --partitions:定义分区数
- --topic:定义 topic 名称
- -------------------------------------------------------------------------------------
-
- //查看当前服务器中的所有 topic
- kafka-topics.sh --list --zookeeper 192.168.10.17:2181,192.168.10.21:2181,192.168.10.22:2181
-
- //查看某个 topic 的详情
- kafka-topics.sh --describe --zookeeper 192.168.10.17:2181,192.168.10.21:2181,192.168.10.22:2181
-
- //发布消息
- kafka-console-producer.sh --broker-list 192.168.10.17:9092,192.168.10.21:9092,192.168.10.22:9092 --topic test
-
- //消费消息
- kafka-console-consumer.sh --bootstrap-server 192.168.10.17:9092,192.168.10.21:9092,192.168.10.22:9092 --topic test --from-beginning
-
- -------------------------------------------------------------------------------------
- --from-beginning:会把主题中以往所有的数据都读取出来
- -------------------------------------------------------------------------------------
-
- //修改分区数
- kafka-topics.sh --zookeeper 192.168.10.17:2181,192.168.10.21:2181,192.168.10.22:2181 --alter --topic test --partitions 6
-
- //删除 topic
- kafka-topics.sh --delete --zookeeper 192.168.10.17:2181,192.168.10.21:2181,192.168.10.22:2181 --topic test
所有机器安装部署 kafka 集群
由于步骤相同,我这里只展示一台设备的搭建!!
- 下载安装包
- 官方下载地址:http://kafka.apache.org/downloads.html
- -------------------------------------
- cd /opt
- wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.7.1/kafka_2.13-2.7.1.tgz
-
- cd /opt
- tar xf 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的全局唯一编号,每个broker不能重复,因此要在其他机器上配置 broker.id=1、broker.id=2
- listeners=PLAINTEXT://192.168.246.7:9092 ●31行,指定监听的IP和端口,如果修改每个broker的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文件(数据文件)保留的最长时间,单位为小时,默认为7天,超时将被删除
- log.segment.bytes=1073741824 #110行,一个segment文件最大的大小,默认为 1G,超出将新建一个新的segment文件
- zookeeper.connect=192.168.246.7:2181,192.168.246.9:2181,192.168.246.12:2181
- #123行,配置连接Zookeeper集群地址
- scp /usr/local/kafka/config/server.properties 192.168.246.9:/usr/local/kafka/config/server.properties
- scp /usr/local/kafka/config/server.properties 192.168.246.12:/usr/local/kafka/config/server.properties
- vim /etc/profile
- export KAFKA_HOME=/usr/local/kafka
- export PATH=$PATH:$KAFKA_HOME/bin
-
- source /etc/profile
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
service kafka start
随便一台机器执行操作就可以
- kafka-topics.sh --create --zookeeper 192.168.246.7:2181,192.168.246.9:2181,192.168.246.12:2181 --replication-factor 2 --partitions 3 --topic test
-
- -------------------------------------------------------------------------------------
- --zookeeper:定义 zookeeper 集群服务器地址,如果有多个 IP 地址使用逗号分割,一般使用一个 IP 即可
- --replication-factor:定义分区副本数,1 代表单副本,建议为 2
- --partitions:定义分区数
- --topic:定义 topic 名称
kafka-topics.sh --create --zookeeper 192.168.246.7:2181,192.168.246.9:2181,192.168.246.12:2181 --replication-factor 2 --partitions 3 --topic test
kafka-topics.sh --list --zookeeper 192.168.246.7:2181,192.168.246.9:2181,192.168.246.12:2181
kafka-topics.sh --describe --zookeeper 192.168.246.7:2181,192.168.246.9:2181,192.168.246.12:2181
生产者推送数据
kafka-console-producer.sh --broker-list 192.168.246.7:9092,192.168.246.9:9092,192.168.246.12:9092 --topic test
#在另外一台主机输入消费信息的命令,查看是否可以收到发布的消息
--from-beginning:会把主题中以往所有的数据都读取出来
kafka-console-consumer.sh --bootstrap-server 192.168.246.7:9092,192.168.246.9:9092,192.168.246.12:9092 --topic test --from-beginning
kafka-topics.sh --zookeeper 192.168.246.7:2181,192.168.246.9:2181,192.168.246.12:2181 --alter --topic test --partitions 6
kafka-topics.sh --delete --zookeeper 192.168.246.7:2181,192.168.246.9:2181,192.168.246.12:2181 --topic test
为保证 producer 发送的数据,能可靠的发送到指定的 topic,topic 的每个 partition 收到 producer 发送的数据后, 都需要向 producer 发送 ack(acknowledgement 确认收到),如果 producer 收到 ack,就会进行下一轮的发送,否则重新发送数据。
LEO:指的是每个副本最大的 offset;
HW:指的是消费者能见到的最大的 offset,所有副本中最小的 LEO。
follower 发生故障后会被临时踢出 ISR(Leader 维护的一个和 Leader 保持同步的 Follower 集合),待该 follower 恢复后,follower 会读取本地磁盘记录的上次的 HW,并将 log 文件高于 HW 的部分截取掉,从 HW 开始向 leader 进行同步。等该 follower 的 LEO 大于等于该 Partition 的 HW,即 follower 追上 leader 之后,就可以重新加入 ISR 了。
leader 发生故障之后,会从 ISR 中选出一个新的 leader, 之后,为保证多个副本之间的数据一致性,其余的 follower 会先将各自的 log 文件高于 HW 的部分截掉,然后从新的 leader 同步数据。
注:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。
对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等 ISR 中的 follower 全部接收成功。所以 Kafka 为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡选择。
当 producer 向 leader 发送数据时,可以通过 request.required.acks 参数来设置数据可靠性的级别:
●0:这意味着producer无需等待来自broker的确认而继续发送下一批消息。这种情况下数据传输效率最高,但是数据可靠性确是最低的。当broker故障时有可能丢失数据。
●1(默认配置):这意味着producer在ISR中的leader已成功收到的数据并得到确认后发送下一条message。如果在follower同步成功之前leader故障,那么将会丢失数据。
●-1(或者是all):producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成,可靠性最高。但是如果在 follower 同步完成后,broker 发送ack 之前,leader 发生故障,那么会造成数据重复。
三种机制性能依次递减,数据可靠性依次递增。
注:在 0.11 版本以前的Kafka,对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据做全局去重。在 0.11 及以后版本的 Kafka,引入了一项重大特性:幂等性。所谓的幂等性就是指 Producer 不论向 Server 发送多少次重复数据, Server 端都只会持久化一条。
- 81 (id: -2 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
- [2024-04-12 23:09:56,300] WARN [Producer clientId=console-producer] Bootstrap broker 192.168.246.7:2181 (id: -1 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
- [2024-04-12 23:09:56,410] WARN [Producer clientId=console-producer] Bootstrap broker 192.168.246.12:2181 (id: -3 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
- [2024-04-12 23:09:56,517] WARN [Producer clientId=console-producer] Bootstrap broker 192.168.246.9:2181 (id: -2 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
生成者生产数据时,端口可能写错了,要写自己监听的端口,本文是9200
- ERROR org.apache.kafka.common.errors.InvalidReplicationFactorException: Replication factor: 2 larger than available brokers: 1(kafka.admin.TopicCommand$)
-
- ##三台kafka只起来一台,查看是否配置文件中的broker.id相同了,或者其他俩台防火墙启动错误
安装zookeeper和kafka后启动报错,查看日志显示有no route host 没有路由等信息,则表示是三台中有防火墙未关闭
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。