1. 常见的MQ
Kafka, ActiveMQ, RabbitMQ, RocketMQ
在大数据场景下,主要使用Kafka,在javaee中主要采用ActiveMQ, RabbitMQ, RocketMQ
2. MQ作用
(1)削峰
(2)解耦
(3)异步
3. 消息队列的模式
(1)点对点模式
(2)发布订阅模式
1. 在同一个消费者组中(每条消息只能被该组中的一个消费者消费),每个分区只能由一个固定消费者进行处理,否则后续很难维护;
2. 分区有leader和follower之分,读写只在leader副本上进行,follower副本(HA)只负责数据同步;
3. zk记录集群节点状态,记录副本的leader信息,leader选举。由于zk逐渐成为了kafka的瓶颈,去除zk是后续的方向
(1)broker.id:集群中每个节点的唯一编号,不能重复
(2)log.dir:日志存储目录
(3)zookeeper.connect:zk连接信息,而且建议创建指定目录存放,否则kafka信息会打散到各个地方
(1)topic:
1)create: 1个分区,3个副本
bin/kafka-topics.sh --bootstrap-server server01:8081 --topic demo --create --partitions 1 --replication-factor 3
2)list:
bin/kafka-topics.sh --bootstrap-server server01:8081 --list
3)describe:
bin/kafka-topics.sh --bootstrap-server server01:8081 --describe
4)alter: 将分区数改成3,分区数只能增加,因为如果减少的话,合并后的分区无法确定消费者的offset。副本数无法通过命令行进行修改
bin/kafka-topics.sh --bootstrap-server server01:8081 --alter --partition 3
(2)producer:
bin/kafka-console-producer.sh --bootstrap-server server01:8081 --topic demo
(3)consumer:
bin/kafka-console-consumer.sh --bootstrap-server server01:8081 --topic demo --from-beginning
涉及两个线程:main线程和sender线程,main线程中创建了一个双端队列RecordAccumulator,main线程将消息发送给RecordAccumulator,RecordAccumulator中的消息达到指定大小或者等待指定时长后,通过sender线程从RecordAccumulator中将消息取出来发送到Kafka broker。
发送后,默认可以最多有5个批次的数据不进行应答,超过后不再向kafka发送数据。
异步发送是指:
外部数据发送到kafka client的RecordAccumulator队列中就算发送完毕,对后续的数据从RecordAccumulator队列发送到Kafka broker不再关心。
同步发送是指:
外部数据发送到kafka broker之后才算完成,才会发送下一批数据。
代码:
1. 依赖
org.apache.kafka:kafka-clients:3.0.0
2. 逻辑代码
(1)普通异步发送代码
(2)带回调方法的异步发送代码
回调方法获取到的返回的元数据信息是从RecordAccumulator中返回的。
1. 分区好处
2. 分区策略
3. 自定义分区策略
1)编写自定义分区器
2)将自定义分区器注册到properties中
batch.size: 批次大小,默认16K,可以修改为32K;
linger,ms: 等待时间,修改为5-100ms;
compression.type: 压缩,例如snappy;
RecordAccumulator: 缓冲区大小,修改为64M。
注意吞吐量与消息延时的权衡。
代码:
1. 数据传递语义
(1)幂等性原理
开发方法:enable.idempotence,默认为true,关闭时设置为false
(2)生产者事物
zk主要记录三大类信息:
1. broker节点,比如[0, 1, 2]
2. broker主题分区leader信息和isr信息
3. controller信息(每个broker中都有一个controller模块,启动后,向zk注册,注册成功的节点为集群的controller节点,后续的leader选举由该节点的controller模块完成)
1. broker启动后,向zk注册自己
2. 注册controller,注册成功的将作为leader选举的controller
3. controller监听broker节点,选举分区leader(按照AR列表顺序,并且位于ISR列表,顺序轮询),将选举结果和ISR信息注册到zk
4. 其他controller从zk同步数据
新节点服役
新节点加入集群后,默认不会分担原有的主题和分区,无法做到负载均衡。如果到进行负载均衡:
1. 创建一个负责均衡主题
vim topics-to-move.json
{"topics" : [{"topic":"first"}, {"topic":"second"}], "version" : 1}
2. 生成一个负载均衡计划
bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 --topics-to-move-json-file topics-to-move,json --broker-list "0,1,2,3" --generate
执行前:
3. 创建副本存储计划(所有副本存储在broker0, broker1, broker2和broker3中)
vim increase-replication-factor.json
旧节点退役
基本信息
Leader和Follower故障处理
LEO:LEO是最新的offset + 1,因为offset是从0开始的。每个副本对应一个LEO
HW:所有副本中最小的LEO。一个分区(分区可以有多个副本)对应一个HW。消费者可见的最大offset = HW - 1。
(1)Follower故障
(2)Leader故障
分区副本分配
手动调整分区副本存储
Leader Partition负载均衡
原则上不建议将再平衡配置参数设置为true,因为再平衡耗时较长,大大降低kafka性能,即使要开始,建议将临界值10%增加,不要频繁触发再平衡。
增加副本因子
文件存储
一个Segment的大小为1G
文件清楚策略
删除时,基于时间的,那么最小判断单元就是segment,segment的过期时间以最后进入的消息的时间起算。
(2)压缩
kafka采用拉模式进行消息的消费
(1)总体工作流程
(2)消费者组原理
(3)消费者组初始化
1)用消费者组的groupId对对50取模(因为存储消费者offset的系统主题“__consumer_offset”的分区数为50),获取到当前group提交offset对应的主题分区,该分区所在broker上的coordinator作为该消费者组的老大;然后该group内的所有消费者向该coordinator发送加入group请求;
2)coordinator随机选取group中的一个consumer作为leader,coordinator将要消费的topic信息发送给consumerLeader;
3)consumerLeader执行消费方案,并将消费方案发送给coordinator;
4)coordinator将消费方案下发给各个consumer;
5)各消费者按照消费方案进行消费,同事保持与coordinator的心跳连接,并在以下情况进行消费再平衡:
a)消费者被移除;b)消费者处理时间过长
(4)消费者消费数据流程
1)消费者端建立网络客户端:ConsumerNetworkClient,用于和kafka服务端集群进行连接;
2)消费者调用sendFetches方法,用来初始化抓取数据配置,其中的主要参数如下:
fetch.min.bytes:每批次最小住区的字节数,默认是字节;当broker端没有这么多数据时,不抓取;
fetch.max.bytes:每批次最大抓取的数据大小,默认是50m;
fetch.max.wait.ms:超时时间,默认500ms,超过该时间时,即使字节数未达到也会抓取数据;
3)调用send方法向kafka服务器请求数据,发送send方法后,会通过回调方法onSuccess将请求的结果拉取到缓冲queue中;
4)消费者从缓冲queue中拉取数据进行处理,默认每次拉取500条;数据的处理过程包括:
反序列化--->拦截器--->处理数据。
1. 独立消费者订阅topic
Duration.ofSeconds(1): 指每次拉取数据之间的间隔时间为1s
2. 独立消费者订阅分区
3. 消费者组
4. 分区的分配与再平衡
(1)Range分配策略
1)如果消费时发生数据消费再平衡,那么退出的节点应当消费的数据会全部分配给存活节点中的一个节点上;
2)节点推出后,再发送数据时,分区会重新均衡分配给所有存活节点。
(2)RoundRobin分配策略
1)如果消费时发生数据消费再平衡,那么退出的节点应当消费的数据会按轮询方式均衡分配给所有存活节点;
2)节点推出后,再发送数据时,分区会重新按照轮询方式均衡分配给所有存活节点。
(3)Sticky分配策略
2)如果消费时发生数据消费再平衡,那么退出的节点应当消费的数据会均衡分配给所有存活节点;
3)节点推出后,再发送数据时,分区会重新按照粘性方式均衡分配给所有存活节点。
5. offset
(1)offset的默认维护
(2)offset的自动提交
(3)offset的手动提交
1)同步提交:消费者拉取一批数据后,只有commnit成功之后才会再次拉取下一批数据
2)异步提交:消费者拉取一批数据后,只要提交了commnit请求,但不关心该请求是否成功,就可以再次拉取下一批数据
(4)指定offset消费
(5)漏消费和重复消费
重复消费:已经消费了数据,但offset没有提交成功,导致数据再次被消费
漏消费:先提交offset后消费数据,但消费可能会失败,导致造成数据的漏消费
如何使消费者既不重复消费,又不漏消费呢?消费者事务
(6)消息积压
https://www.kafka-eagle.org
需要安装mysql用于存储可视化展示的数据
不再需要zk
Flume在大数据开发中非常常见,可以用于kafka的生产者,也可以用于kafka的消费者
(1)Flume生产者
(2)Flume消费者
(1)Flink生产者
1)导入依赖
2)编码
(2)Flink消费者
(1)Kafka生产者
(2)Kafka消费者
(1)场景
(2) 服务器
20m/s * 2 = 40 / 100 < 1, 向上取整,也就是取1,最终等于 2 * 1 + 1 = 3
(3) 磁盘
一天大概1亿条数据,每条消息的大小按1k计算,大概就是100g,2个副本,一共200g;数据默认存储3天,一共就要600g,然后加上一点buffer,除以0.7,大概需要1t。
因为是顺序读写,机械硬盘和固态硬盘性能差别不大,因此采用机械硬盘。
(4) 内存
1)kafka堆内存
一般配置10-15g。使用jstat -gc 2732 ls 10查看YGC次数,如果YGC次数特别高,需要增加堆内存。
jmap -heap 2321查看堆内存使用情况,如果使用过高,需要增加堆内存
2)kafka页缓存
(5)CPU选择
(6)网络
参数修改
(1)生产者核心配置
1)如何提高吞吐量
2)数据可靠性
4)数据有序
单分区内有序(有条件的,不能乱序);多分区,分区与分区之间乱序
1. 服役新节点,退役旧节点
2. 新增分区
3. 新增副本因子(不能通过命令行增加)
4. 手动调整分区副本存储
5. LeaerPartition负载均衡
6. 自动创建主题
http://kafka.apache.org/downloads