kafka学习笔记

kafka是一个消息队列,
消息队列屏蔽了底层复杂的通讯协议,消息队列解决的是通信问题。
全球消息处理性能最快的一款MQ

基础概

 

 


- 生产者将消息发送给broker,broker会将消息保存在本地的日志文件中。
/usr/local/kafka/data/kafka-logs/主题-分区/0000000.log
- 消息的保存是有序的,通过offset偏移量来描述消息的有序性
- 消费者消费消息时也是通过offset来描述当前要消费的那条消息的位置

kafka中单播和多播消息的实现
单播消息:如果多个消费者在同一个消费组,只有一个消费者可以收到订阅的topic的消息;即同一个消费组中只能有一个消费者可以收到一个topic中的消息

多播消息:如果两个消费者在不同的消费组,且订阅同一个topic,则这两个消费者都能够收到消息。

查看消费组及信息

复制代码
 I have no name!@5c7ac4262881:/opt/bitnami/kafka/bin$ ./kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --list
'rcrai:ai-async-task-mgr:e3158986-b159-11ea-a1cc-00155d68e297'
qs
kanban-report-etl
bz-factory-default
es-etl-batch
es-etl
dealtape-default
rta
I have no name!@5c7ac4262881:/opt/bitnami/kafka/bin$ ./kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --describe --group rta

TOPIC                        PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG             CONSUMER-ID                                 HOST            CLIENT-ID
rta-session-end-event        5          -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
rta-session-end-event        2          -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
rta-session-end-event        24         -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
rta-session-end-event        23         -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
rta-session-end-event        29         -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
rta-session-end-event        22         -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
rta-session-end-event        15         -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
rta-session-end-event        9          -               0               -               sarama-6e8fdb6f-8556-41a9-a720-71d16ab2ac2f /172.27.0.1     sarama
复制代码

 

current-offset:当前消费组的已消费偏移量
Log-end-offset:主题对应的分区消息的结束偏移量
Lag:当前消费组未消费的消息数

主题和分区的概念

tiopic主题:kafka逻辑的概念。kafka通过topic将消息进行分类。不同topic会被订阅该topic的消费者消费;如果topic中的消息很多,需要几T来保存。为了解决文件过大的问题,提出了partition的概念
partition分区:
- 分区存储可解决文件过大的问题;
- 可以提高读写的吞吐量,读写可以在多个分区中同时进行
kafka中的/usr/local/kafka/data/目录中
- 有个index文件,是稀疏索引的作用。
- 000.log是保存的消息
- _consumer_offsets_0到_consumer_offsets_49等:创建了50个分区,用来存放消费者消费某个主题的偏移量
- 同一个消费组中有一个消费者在消费的过程中会将偏移量提交到_consumer_offsets(key是consumerGroupId+topic+分区,value是偏移量的值),当这个消费者意外挂掉了,在该组中新启动的消费者会在这个topic中找到已经消费的偏移量然后继续消费
- 由于_consumer_offsets可能接收高并发请求,kafka默认分配给这50个分区,分配机制是:哈希算法
- 文件中保存的消息默认保存7天。
副本概念的介绍
在创建主题的时候除了指明主题的分区数以外,还创建了副本。
副本是为了主题中的分区创建多个备份,多个副本在kafka集群中的多个broker中,会有一个副本作为leader,其他的是follower。
leader:kafka的读写操作都发生在leader上
follower:接收leader的同步数据。
isr:可以同步的broker节点和已同步的broker节点,存放在isr中。作用:当leader挂了,新选的leader会在isr集合中产生。如果isr中的节点性能较差会被踢出isr集合中

集群消息的发送和消费
关于分区消费组消费者的细节
集群中有多个broker,每个broker有多个partition,一个partition只能被一个消费组的某一个消费者消费;一个消费组中的一个消费者可以消费多个partition的。
kafka只能保证partition的范围内保证消息消费的局部顺序性,但是不能保证一个topic中多个partition的消费顺序性

- 一个partition只能被一个消费组中的一个消费者消费,目的是保证消费的顺序性,但是多个partition的多个消费者的总的顺序性在这里得不到保证。
- partition的数量决定了消费组中消费者的数量,建议同一个消费组中消费者的数量不要超过partition的数量,否则多出的消费者消费不到消息
- 如果消费者挂了,会触发rebalance,会让其他的消费者来消费该分区
生产端发送消息的同步发送和异步发送(在程序设计的时候需要注意)
同步发送:如果生产者发送消息没有收到ack,生产者会阻塞,阻塞到3s的时间,如果还没有收到消息会进行3次重试。
异步发送:消费发送后,直接继续后面的流程。这种方法容易造成消息丢失。

ack=0;kafka不需要任何broker接收到消息就可以返回ack给生产者,容易丢数据,但是效率很高
ack=1;生产者将数据上传到kafka之后,多个副本的leader完成数据写入之后,就返回ack;这种情况下副本没有完成备份,如果leader此时挂了,就会导致数据丢失。数据保证和效率相对均衡。
ack=-1或者all,数据需要同步到所有的副本之后才会返回给ack;数据有保证,但是效率低

发送消息的缓冲区机制
生产者发送10万条消息就会建立10万个链接吗?不是
是有个缓冲区,缓冲区默认32mb(可配置);生产者有个本地线程,每次从缓冲区取16k(可配置)的数据发送到broker,如果缓冲区的数据不足16k,会过10ms之后直接将已有数据拉取发送。

消费者的消费细节
自动提交offset,和手动提交offset
不论是那种提交方式,都需要把所属的消费组h+消费的某个主题+消费的某个分区以及消费的偏移量,这样的信息提交到集群的_consumer_offsets主题里面。
自动提交offset:消息poll下来以后,直接自动提交offset;这种模式容易丢失offset。
手动同步提交:在消费完消息后,调用同步提交方式,当集群返回ack之后表示提交成功,执行之后的逻辑
手动异步提交:在消息消费完之后,不需要等到集群的ack


长轮询poll消息。默认情况下,消费者会一次poll500条消息;
如果一次poll到了500条,后面直接执行业务循环,如果没有poll到500条且时间在1s内,那么长轮询继续poll,要么到500条,要么到1s;
如果多次poll都没有达到500条;且1s时间到了那么直接执行后续的业务循环。

如果两次poll间隔超过30s;会认为该消费者的消费能力不足,该消费者会被提出消费组,之后rebalance;出现rebalance的时候胡影响性能,可以通过设置一次poll的消息数量,来进行控制。

消费者的健康检查;消费者每隔一秒向kafka集群发送心跳,如果集群发现超过10s没有接收到消费者的心跳,则认为消费者出现问题,就会踢出消费者,然后rebalance。

新消费组消费offset的规则
新消费组的消费者启动的时候,默认从当前分区的最后一条消息的offset+1开始消费(消费新的消息);可以通过一下的设置,让新的消费者第一次从头开始消费
latest
earliest

kafka集群中的controller、rebalance、HW(高水位)
controller:
集群中谁来充当controller,每个broker启动时会向zk创建一个临时序号节点,获得的序号最小的那个broker将作为集群的controller。负责管理整个集群中的所有分区和副本状态。
- 当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本,选举规则是从isr集合中最左边获得
- 当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新器元数据信息。
- 当使用kafka-topic.sh脚本为某个topic增加分区数量时,同样还是由控制器负责让新分区被其他节点感知到。

rebalance
前提:消费组中的消费者没有致命分区来消费。
触发条件:当消费组中的消费者和分区发生变化的时候
分区分配策略:在rebalance之前还有三种策略:
- range:根据公式计算得到每个消费者消费哪几个分区:
- 轮询:轮着来
- sticky:粘合策略,如果需要rebalance,会在之前分配的基础上调整,不会改变之前的分配情况,如果这个策略没有打开就要进行全部的重新分配,建议开启。

HW(高水位)
LEO是某个副本最后消息的消息位置
HW是已完成同步的位置,消息在写入broker时,且每个broker完成这条消息的同步后,hw才会变化,在这之前消费者消费不到这条消息。在同步完成后,hw更新之后,消费者才能消费到这条消息,这样的目的是防止消息的丢失。

kafka线上问题优化
1. 如何防止消息丢失
- 发送方:ack是1或者-1/all 可以防止消息丢失;使用同步发送。并且设置同步的分区数>=2
- 消费方:把自动提交改成手动提交
2. 如何防止消息的重复消费
在防止消息丢失的方案中如果生产者发送完消息后,因为网络抖动,没有收到ack,但是实际上broker已经收到了消息,此时生产者会进行重试,于是broker就会收到多条相同的消息,而造成消费者的重复消费。
幂等性的保证
方案一:在数据库中创建一个联合主键,id(主键自增),order_id(业务id);两个主键都不能相同
方案二:分布式锁,以业务id为锁,保证只有一条消息可以写入
3. 如何做到顺序消费
在生产者这边:使用同步发送,ack非零
消费者:主题只能设置一个分区,消费组中只能有一个消费者。
顺序消费会影响kafka的性能。

4. 解决消息积压问题
消息积压问题的出现,
消息的消费者的消费速度,远远赶不上生产者的生产消息的速度,导致kafka中有大量的数据没有被消费,随着没有被消费的数据堆积的越来越多,消费者寻址的性能会越来越差,最后导致整个kafka对外提供服务的性能很差,从而造成其他服务访问速度也变慢,造成服务雪崩

如何解决呢?
- 使用多线程:在一个消费者中使用多线程,充分利用机器的性能进行消息的消费
- 创建多个消费组,多个消费者,部署到其他机器上,提高消费者的消费速度
- 通过业务的架构设计,提升业务层面的消费速度。
5. 延时队列
延时队列的应用场景:在订单创建成功后如果超过30分钟没有付款,则需要取消订单,此时可以使用延时队列来实现。

posted @   王广福  阅读(327)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示