资源:https://www.bilibili.com/video/av65544753?from=search&seid=8697370751225524328
P1-p2-: 简介
- P3: 介绍了一下消息队列的应用场景-----可以使业务异步-------优势:业务解耦—>可用性、可恢复性 。 缓冲:可以解决生产>消费速度不一致的问题。 压力分配(削峰):在突发流量的情况下不影响关键业务,且具有灵活性,可以扩充这个集群的机器数。
- P4: mq-点对点模式:一对一,只能给一个client用,用后即删。 发布订阅模式:一对多。 而因为生产者生产速度和每一个消费者消费速度不一样,所以存在两种方式:1是生产者主动push,2是消费者主动pull。 kafka属于第二种。优点在于不会因为生产者push速度过快而导致下游崩掉,或者消费者速度过快而资源浪费。但这种也存在一个缺点:存在一个长轮询一直去pull新消息。
- P5 介绍topic的分类作用以及主题分区partition的提高负载均衡的能力,同一个主题下的一个分区可以放在集群的多个机器上(分布式), 同时也提高了并发。 当一个分区在多个集群上时,会存在leader和follow,从节点属于副本,仅仅用来做备份,或者升级为leader。所以我们只能连接leader。作用:高可用。
介绍了消费者组的概念。一个分区下的消息只能被同一个消费者组里面的一个消费者消费。(这里意味着,如果同一个分区下的消息是有序的)但可以同时被两组消费者消费。 消费者组的意义在于可以提高消费能力,同一个组下每多一个消费者就意味着平均消费量减少,但当消费者数量大于分区数量就没意义了。zookeepeer 作用是什么? 没说
消费者存储的东西: 维护offset且保存在zk中(0.9版本之后存在kafka本地,持久化在磁盘中!),这样消费者挂了的话,新启动的消费者可以接着消费。 - P6kafka的安装,配置,启动的脚本等等。
- P7 kafka命令行, topic 的增删改查
- P8 命令行控制生产消费者 ,最原始的生产消费方法—-可以注意下其需要的参数
- P9 数据日志的存放等等
- P10 回顾内容,以及一个建议 一定要自己动手安装一次,操作一次!
- P11
- P13 生产者分区策略
分区优点前面提过,当生产者发送数据时,会将数据封装成一个对象,此时的参数 :
topic必须指定,而partition有三种方式:
1.直接指定。
2.没指定但有k-v,会把key的hash值和p的数量取余确定发送给哪个p。
3.啥都没指定,此时round-robin,轮询给(从某个partrion开始往后一个p给一次)。 第一次的位置是随机生成的整数和p数量取余确定。 - P14 生产者数据的保证
partion接到数据之后,会向生产者回一个ack。但如果说是集群有多个partition,此时的情况是如何呢?
前面我们知道生产者只和leader交接数据,leader收到数据之后会和follow同步副本。此时存在两种机制
1.半数以上的节点完成同步就发ack,延迟低但是选举新leader的时候,如果希望集群能容忍n个节点宕机则需要2n 1个副本。换句话说提高了集群高可用的成本。
2.全部完成同步发送ack,延迟高但是选举新leader时,希望容忍n个节点宕机只需要n 1个副本。
kafka选择第二种方式,因为数据不会冗余,且网络延迟对kafka影响小,
**?**我在这里的理解方式是,因为如果不全部同步的话,那么可能每个机器上的数据都不完整,要组合出来完整的数据就需要更多的机器来参与进来,所以集群成本更高!
第二种方式存在一个问题就是如果一个从节点挂了,那么leader一直在等待,永远不会发送ack,所以引入isr优化
ISR(同步副本): leader维护了一个动态的set,我理解为选出一些leader候选节点,
1 这些节点保证通信快速
2 保证数据完全一致
因为会动态维护, 所以1.节点的响应时间太长默认10秒钟踢出去,小于的拉进来。2. 当节点数据量大于阈值默认10条踢出去,小于的拉进来。
高版本去掉了第二个条件,为什么呢? 因为生产者是批量发数据,当生产者一次发送过多数据的时候,容易造成leader数据量-follower数据量大于阈值,会清空ISR,而副本同步完成后又会重新拉进来。造成性能浪费。而且isr写在zk里面,这样会频繁操作zk,造成zk的负荷。 - P15 生产者的ack机制
前面提到的全部同步机制还是有速度较慢的问题,而使用场景里有的数据可靠性要求不高,不需要ack。所以kafka有如下配置
acks=0,不等待任何返回,生产者只发一次。broker挂了就丢失数据。
acks=1,只等待leader写完,如果follower还没同步完成,leader挂了则数据丢失。
acks=-1或者all,会等待isr中所有的同步完成,才返回。这种情况几乎不会丢数据,除非当isr退化到只有leader时,等于acks=1的情况。
值得注意的是,此时存在数据重复发送情况
当leader接受完数据同步给follower之后但还没有发送ack时挂了,这时生产者会重发,这边会重新选主,所以同一条信息就会产生两次。
-
P16 数据一致性问题
存在一种消费者消费情况
L 10 此时leader挂了
f1 8
f2 9
选f1也leader,消费者看到的数据不一致。
选f2为leader时,L又活过来了,此时出现数据不一致。
所以引入hw和leo
leo 每个副本维护的最后一个offset
hw=high watermark,高水位,维护所有副本中的最小leo,只给消费者暴露hw之前的数据,保证 当leader挂了时,重新选主时,不会影响消费者消费数据的一致性问题。
所以hw可以理解为消费者看到的消息的位置最大值!
值得注意的是,这个只保证消费者消费数据数据一致。而丢不丢失数据,数据重复不重复是ack保证的。
第二点是,当新leader被选举出来的时候会广播一条消息,其他从节点就从hw的位置删掉多余部分,保持一致。之后就从leader获取数据 -
P17 exactlyOnce
先回顾一下acks有几个值
当其为0时,保证每条消息至多只发送一次,保证不会数据重复
-1时至少会发送一次。保证会不丢失数据。
也许场景更多时候需要精准一次,即既不丢失也不重复。我们可以想到 至少一次 去重=精准一次
kafka引入幂等性:
首先需要把生产者中的参数idompotence设置为true。
然后系统会给每一个启用了此特性的生产者分配一个id。发往同一个partion的消息会附带一个序列号。
broker端会对 pid.partition.seqnumber 做主键缓存,以次保证不重复
?这里关于seqnumber分配的规则不是特别了解
当生产者重启时,pid会发生变化。此时无法保证精准一次。 -
P18 生产者知识总结
看上面就完事了 -
P19 消费者分区分配策略
前面提过消费者主要是拉取消息。
策略是建立在有多个消费者消费的情况下,如果只有一个消费者那就所有的分区消息都会给这一个消费者消费。
pull的方式会有长轮询,如果没消息,消费者会一直返回空,针对这点,消费者消费时可以传一个timeout参数,如果当前没消息,会等待这么长的时间再去拉取。
一个消费组能订阅多个topic,一个topic有多个partition,一个组里面也有多个消费者,此时涉及到分配问题。
第一种randrobin,会把所有订阅的主题的partion当成一个主体来轮询分配。 百度一张图就好了。
优点是所有消费者分配的p的最大差值为1,
但这种方式有一个前提条件是这个组必须消费同一个主题,否则就会出现错误,会出现消费者消费到自己没订阅的topic的情况。
第二种是默认的方式:range,按主题划分。
比如一个主题下有7个partition,被一个有三个消费者的消费组订阅,那么partition就会分成012,34,56分给三个消费者。
这样的问题就是有的消费者会消费更多p,随着订阅的主题越多,现象越明显。这里显然只要按主题划分,不管里面如何分配都存在这个问题。
策略被触发的时候:当消费者组内消费者的数量发生变化的时候(包括新启动一个或者挂了一个消费者),会调用策略重新分配。这里注意的是哪怕加入新的消费者之后数量大于p的数量,也会重新分配。 -
P20 消费者offset的存储:
offset保证消费者**(挂了重新拉起来之后或者有新的消费者进入消费者组的时候)**能够继续消费,在zk和本地都有保存(不同版本不同)。 所以此主键由三个确定: 消费者组group+topic+partion 。
这一集有一个小实验: 启了一个bigdata的topic,起了两个消费者,然后展示了kafka在zk中保存的信息:topic、partion、consumer的group+offset等等。 (高版本中offset 保存在本地的topic中,这一集也展示了如何获取这个topic中的offset值)
ps:顺便在这个实验中我们可以发现:一个topic被多个group订阅时,每个group都会从头开始消费一遍整个topic中的消息 -
P21 消费者组 案例
场景:验证了topic中的消息只会被一个消费者组中的一个消费者消费。以及验证了新加入消费者会重新分配partition的规则。