实现原理
观察者模式
即 → 订阅者模式
例子:
1. 微博博主给粉丝发送动态
2. 每次狼出门之前先给人打个电话,通知人们自己要去吃羊.
生产者和消费者(消息)
传统模式
-生产者直接将消息传递给指定的消费者
-耦合性特别高,当生产者或者消费者发生变化,都需要重写业务逻辑
新型模式
-生产者和消费者之间建立一个共享的缓冲区
-生产者负责向里面添加数据
-消费者负责从里面取出数据
-一般遵循先进先出的原则
缓冲区
-一个工作组只能对某一条消息消费一次
-缓冲区的消息可以被多个工作组消费
-内部肯定有一定的机制来管理或者维护不同的数
据
-缓冲区的数据需要放在多个节点上,让更多的节点参与到计算
-每个节点持有消息的一个分区,属于数据的一部分
-当生产者产生消息之后,需要先计算对应的分区
架构图
Broker – 代理
-集群的节点,用于处理数据
Topic – 主题
-不同的数据消息交给不同的Topic管理
-类似于Table或者Type
-存储数据可以去指定的主题去操作
producer – 生产者
-往broker中某个topic里面生产数据
consumer – 消费者
-从broker中某个topic获取数据
Partition – 分区
-一个Topic下可以有多个分区,数据真实存放的位置
-当生产者产生数据的时候,根据分配策略(Hash取模),选择分区
-然后将消息追加到指定的分区的末尾(队列)
-每条消息都会有一个自增的编号
-标识顺序
-用于标识消息的偏移量,有专门的索引信息
offset - 偏移量
-可以唯一的标识一条消息
-消费者消费消息的时候就是通过偏移量来决定下次读取哪条消息
-消息被消费之后,并不被马上删除,这样多个业务就可以重复使用kafka的消息
-我们某一个业务也可以通过修改偏移量达到重新读取消息的目的,偏移量由用户控制
-消息最终还是会被删除的,默认生命周期为1周(7*24)
-偏移量决定读取数据的位置,不会有线程安全的问题
replication - 数据备份
-数据会存放到topic的分区中,但是有可能分区会损坏
-我们需要对分区的数据进行备份(备份多少取决于你对数据的重视程度)
-我们将分区的分为Leader(1)和Follower(N-1)
-Leader负责写入和读取数据
-Follower只负责备份
-保证了数据的一致性
-备份数设置为N,表示主+备=N
Consumer Group – 消费者组
将多个消费者集中到一起去处理某一个Topic的数据
可以更快的提高数据的消费能力
整个消费者组共享一组偏移量(防止数据被重复读取),因为一个Topic有多个分区
Kafka环境搭建
需要先搭建Zookeeper环境
Kafka要基于Zookeeper搭建
配置Kafka
--解压kafka的tgz包:
tar -zxvf kafka_2.11-0.8.2.1.tgz
--移动解压后目录:
mv kafka_2.11-0.8.2.1 /opt/sxt/
--进入软件安装目录并修改目录名:
cd /opt/sxt/
mv kafka_2.11-0.8.2.1/ kafka_2.11
```powershell
--修改配置文件
cd /opt/sxt/kafka_2.11/config/
vim server.properties
配置文件修改项 :
行数20 broker.id=0
行数25 port=9092
行数58 log.dirs=/var/sxt/kafka-logs
行数118 zookeeper.connect=bd1301:2181,bd1302:2181,bd1303:2181
--将kafka文件目录拷贝到其他主机:
scp -r kafka_2.11/ root@bd1302:/opt/sxt/
scp -r kafka_2.11/ root@bd1303:/opt/sxt/
--修改其他机器上的配置文件
vim server.properties
这里只需修改broker.id
主机2
20行 broker.id=1
主机3
20行 broker.id=2
--添加环境变量
vim /etc/profile
--拷贝复制环境变量到其他主机
scp /etc/profile root@bd1302:/etc/profile
scp /etc/profile root@bd1303:/etc/profile
--加载环境变量
source /etc/profile
启动集群
--启动zookeeper集群(所有)
zkServer.sh start
--启动ksfka集群(所有)
kafka-server-start.sh /opt/sxt/kafka_2.11/config/server.properties
常见命令代码示例:
- //创建主题
--在非集群启动的主机1上输入代码
kafka-topics.sh --zookeeper bd1301:2181,bd1302:2181,bd1303:2181 --create --replication-factor 2 --partitions 3 --topic xxxxxgy
- //查看所有主题
--在非集群启动的主机1上输入代码
kafka-topics.sh --zookeeper bd1301:2181,bd1302:2181,bd1303:2181 --list
- //查看主题
--在非集群启动的主机1上输入代码
kafka-topics.sh --zookeeper bd1301:2181,bd1302:2181,bd1303:2181 --describe --topic xxxxxgy
- //创建生产者
–在非集群启动的主机1上输入代码
kafka-console-producer.sh --broker-list bd1301:9092,bd1302:9092,bd1303:9092 --topic xxxxxgy
之后自由输入数据
- //创建消费者
--再新启动另一主机1进行测试
kafka-console-consumer.sh --zookeeper bd1301:2181,bd1302:2181,bd1303:2181 --from-beginning --topic xxxxxgy
ISR机制
我们备份数据就是防止数据丢失,当主节点挂掉时,可以启用备份节点
主备节点的数据一致性
-acks :默认为1
-0 : 生产者只负责产生消息,具体是否存放完成不关心
-1:Leader存放到本地,但是从节点是否同步不关心
-all:不但主节点存放,而且从节点已经同步完成
-我们写数据只写到leader中,Follower如何同步数据?
-Leader → push
-Follower → pull
-Follower每间隔一定时间去Leader拉取数据,来保证数据的同步
-ISR(in-syncReplica)
-当主节点挂点,并不是去Follower选择主,而是从ISR中选择主
-判断标准
-超过10秒钟没有同步数据
-replica.lag.time.max.ms=10000
-主副节点差4000条数据
-rerplica.lag.max.messages=4000
-脏节点选举
-kafka采用一种降级措施来处理:
-选举第一个恢复的node作为leader提供服务,以它的数据为基准,这个措施被称为脏leader选举
JavaAPI
生产者
创建一线程重复的向kafka输入数据
- 配置配置信息
- 开启线程写入数据
//封装消息对象
KeyedMessage<String, String> message = new KeyedMessage<>(topic, key, value);
//将消息发送到Kafka
producerForKafka.send(message);
消费者
创建一线程重复的向kafka消费数据
- 配置配置信息
- 开启线程消费数据
//声明一个Map存放 主题与线程数的对应关系
Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
// 描述读取哪个topic,需要几个线程读
topicCountMap.put(topic, 1);
// 获取主题 与 读取流的映射关系 sxtlog 1 sxtteacher 3
Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap = consumer.createMessageStreams(topicCountMap);
// 每个线程对应于一个KafkaStream
List<KafkaStream<byte[], byte[]>> list = consumerMap.get(topic);
// 获取kafkastream流
KafkaStream stream0 = list.get(0);
//获取消息的迭代器,一次性读取一条消息
ConsumerIterator<byte[], byte[]> it = stream0.iterator();
重复消费和数据的丢失
有可能一个消费者取出了一条数据(offset=88),但是还没有处理完成,但是消费者被关闭了
- 如果下次还能从88重新处理就属于完美情况
- 如果下次数据从86开始,就属于数据的重复消费
- 如果下次数据从89开始,就是与数据的丢失
//消费者自动提交偏移量的时间间隔
props.put("auto.commit.interval.ms", "1010");
提交间隔》单条执行时间 (重复)
提交间隔《单条执行时间 (丢失)
Kafka读写数据快
写入数据
-写入数据往内存去写
-基于操作系统的页缓存来实现文件写入的
-操作系统自己管理的缓存
-磁盘读数据
-寻道时间
-机械硬盘顺序读取速度要超过固态硬盘的好多倍
-磁盘转速
读取数据
-读取数据时
-首先去内存区查看有没有这个偏移量的数据
-如果没有这个数据再去数据文件中读取数据,为了节约中间在内存中拷贝数据的时间
-在读数据的时候是引入零拷贝技术
来源:CSDN
作者:BF-LoneSilverWind
链接:https://blog.csdn.net/digua930126/article/details/103569613