文章目录
- 0、消息系统
- 1、Kafka核心概念
- 2、Kafka的特性
- 3、 Kafka的使用场景
- 4、Kafka集群架构
- 5、Zookeeper对于Kafka的作用是什么?
- 6、kafka的命令行的管理使用
- 7、kafka的生产者和消费者api代码开发
- 8、kafka分区策略
- 9、如何保证同一分区一定有序
- 10、kafka的文件存储机制
- 11、Segment file是什么
- 12、kafka如何保证消息消费的有序性呢?
- 13、kafka如何快速查询数据
- 14、Kafka如何不重复消费数据
- 15、Kafka高效文件存储设计特点
- 16、为什么Kafka速度那么快
- 17、kafka监控工具 kafkaManager
- 18、HW&LEO原理
- 19、HW&LEO更新机制
- 20、生产者遇到了异常如何处理?
- 21、Kafka的ack的三种机制
- 22、 如何提升生产者的吞吐量?
- 23、如何保证Kafka内部数据不丢失?
- 24、 积压了百万消息如何处理?
0、消息系统
-
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
-
消息队列,把数据进行持久化,直到它们已经被完全处理,通过这一方式规避了数据丢失风险。
-
许多消息队列所采用的**"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕**,从而确保你的数据被安全的保存直到你使用完毕。
-
因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。
1、Kafka核心概念
kafka是一个分布式消息系统。
具有高性能、持久化、多副本备份、横向扩展能力。
生产者往队列里写消息,消费者从队列里取消息进行业务逻辑。
Kafka就是一种发布-订阅模式。将消息保存在磁盘中,以顺序读写方式访问磁盘,避免随机读写导致性能瓶颈。
2、Kafka的特性
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。
- 可扩展性:kafka集群支持热扩展
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
- 高并发:支持数千个客户端同时读写
3、 Kafka的使用场景
- 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。
- 消息系统:解耦和生产者和消费者、缓存消息等。
- 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
- 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
- 流式处理:比如spark streaming和storm
- 事件源
4、Kafka集群架构
kafka: producer—topic—broker—consumer zookeeper调度
topic—partition (repatition)—leader/follower
broker—broker Controller/ broker follower
-
producer:消息生产者,发布消息到Kafka集群的终端或服务
-
topic
- 每条发布到Kafka集群的消息属于的类别,即Kafka是面向 topic 的。
- 更通俗的说Topic就像一个消息队列,生产者可以向其写入消息,消费者可以从中读取消息
- 一个Topic支持多个生产者或消费者同时订阅它,所以其扩展性很好。
-
broker:Kafka集群中包含的服务器,一个borker表示kafka集群中的一个节点
-
consumer:从Kafka集群中消费消息的终端或服务
-
partition
- 每个 topic 包含一个或多个partition。Kafka分配的单位是partition
- replica:partition 的副本,保障 partition 的高可用。
-
leader
- 每个partition有多个副本,其中有且仅有一个作为Leader
- Leader是当前负责数据的读写的partition。
- producer 和 consumer 只跟 leader 交互
-
follower
- Follower跟随Leader,所有写请求都通过Leader路由,
- 数据变更会广播给所有Follower,Follower与Leader保持数据同步。
- 如果Leader失效,则从Follower中选举出一个新的Leader。
-
consumer group
- 每个 consumer 都属于一个 consumer group,每条消息只能被 consumer group 中的一个 Consumer 消费,但可以被多个 consumer group 消费。
-
controller:Kafka集群的总控组件
管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作
-
负责监听其他broker的所有信息,感知broker的宕机,
-
Kafka集群扩容时,负责把集群里的数据进行负载均衡的迁移,负责监听这个broker的加入
-
管理Kafka集群的各种元数据与partition,负责进行Leader Partition的选举,控制partition的删除,?
-
-
zookeeper:存储集群的元数据信息
-
Kakfa Broker Leader的选举:
-
broker集群受Zookeeper管理。所有的Broker节点一起去Zookeeper上注册一个临时节点,只有一个broker会注册成功,其他的都会失败,成功在注册临时节点的broker,会成为broker Controller,其他的broker叫broker follower。(Controller在ZooKeeper注册Watch)。
-
如果这个broker controller宕机了,在zookeeper上面的那个临时节点就会消失,此时所有的broker又会一起去Zookeeper上注册一个临时节点,先注册成功的又为controller。
-
这个broker controller会读取该宕机broker上所有的partition在zookeeper上的状态,并选取ISR列表中的一个replica作为partition leader
-
-
offset
- 消费者在对应分区上已经消费的消息数(位置),
- offset保存的地方跟kafka版本有一定的关系。
kafka0.8 版本之前offset保存在zookeeper上。
kafka0.8 版本之后offset保存在kafka集群上。
-
ISR机制
- ISR是:in-sync replica,就是跟leader partition保持同步的follower partition的数量,只有处于ISR列表中的follower才可以在leader宕机之后被选举为新的leader,因为在这个ISR列表里代表他的数据跟leader是同步的。
- 光是依靠多副本机制,能保证Kafka的高可用性,但不能保证数据不丢失。因为如果leader宕机,但是leader的数据还没同步到follower上去,此时即使选举了 follower作为新的leader,当时刚才的数据已经丢失了。
5、Zookeeper对于Kafka的作用是什么?
Kafka集群中有一个broker会被选举为Controller,负责管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作。
Controller的管理工作都是依赖于Zookeeper的,Broker Leader的选举时,所有的Broker节点一起去Zookeeper上注册一个临时节点,只有一个broker会注册成功,其他的都会失败,成功在注册临时节点的broker,会成为broker Controller.
6、kafka的命令行的管理使用
- 创建topic:
kafka-topics.sh –create --partitions 3 –replication-factor 2 –topic test --zookeeper node01:2181,node02:2181
- 查询所有的topic:
kafka-topics.sh –list --zookeeper node01:2181,node02:2181
- 查看topic的描述信息
kafka-topics.sh –describe --topic test –zookeeper node01:2181,node02:2181
- 删除topic
kafka-topics.sh –delete --topic test –zookeeper node01:2181,node02:2181
- 模拟生产者写入数据到topic中
kafka-console-producer.sh --broker-list node01:9092,node02:9092,node03:9092 –topic test
- 模拟消费者拉取topic中的数据
kafka-console-consumer.sh --bootstrap-server node01:9092,node02:9092,node03:9092 –topic test –from-beginning
7、kafka的生产者和消费者api代码开发
//kafka生产者代码
//准备配置属性
Properties props = new Properties();
//kafka集群地址
props.put("bootstrap.servers","node01:9092,node02:9092,node03:9092");
//acks它代表消息确认机制
props.put("acks", "all");
//重试的次数
props.put("retries", 0);
//批处理数据的大小,每次写入多少数据到topic
props.put("batch.size", 16384);
//可以延长多久发送数据
props.put("linger.ms", 1);
//缓冲区的大小
props.put("buffer.memory", 33554432);
props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<String, String>(props);
for (int i = 0; i < 100; i++)
producer.send(new ProducerRecord<String, String>("test", Integer.toString(i), "hello-kafka-"+i));
//这里需要三个参数,第一个:topic的名称,第二个参数:表示消息的key,第三个参数:消息具体内容
producer.close();
//kafka消费者代码(自动提交偏移量)
//准备配置属性
Properties props = new Properties();
//kafka集群地址
props.put("bootstrap.servers","node01:9092,node02:9092,node03:9092");
//消费者组id
props.put("group.id", "test");
//自动提交偏移量
props.put("enable.auto.commit", "true");
//自动提交偏移量的时间间隔
props.put("auto.commit.interval.ms", "1000");
//默认是latest
//earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
//latest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
//none : topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常
props.put("auto.offset.reset","earliest");
props.put("key.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);
//指定消费哪些topic
consumer.subscribe(Arrays.asList("test"));
while (true) {//指定每个多久拉取一次数据
ConsumerRecords<String, String> records =consumer.poll(100);
for (ConsumerRecord<String, String> record : records)
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
8、kafka分区策略
kafka的分区策略决定了producer生产者产生的一条消息最后会写入到topic的哪一个分区中,
kafka主要有四种分区策略:(分区号与key值的是否指定)
- 1、给定具体的分区号,直接将数据发送到指定的分区里面去
- 2、没有给定分区号,给定数据的key值,通过key取上hashCode进行分区
- 3、既没有给定分区号,也没有给定key值,直接轮循进行分区
- 4、自定义分区,定义一个类实现接口Partitioner
topic下引入partition的作用:
-
topic是逻辑的概念,partition是物理的概念。
-
为了性能考虑,如果topic内的消息只存于一个broker,那这个broker会成为瓶颈,无法做到水平扩展。
-
kafka通过算法尽可能的把partition分配到集群的不同服务器上。
-
partition也可以理解为segment的封装。一个partition对应多个segment。一个segment包含一个数据文件和一个索引文件。
9、如何保证同一分区一定有序
方案一,kafka topic 只设置一个partition分区
方案二,producer将消息发送到指定partition分区
解析:
方案一:kafka默认保证同一个partition分区内的消息是有序的,则可以设置topic只使用一个分区,这样消息就是全局有序,缺点是只能被consumer group里的一个消费者消费,降低了性能,不适用高并发的情况
方案二:既然kafka默认保证同一个partition分区内的消息是有序的,则producer可以在发送消息时可以指定需要保证顺序的几条消息发送到同一个分区,这样消费者消费时,消息就是有序。
但是个时候还有个问题就是消息重试的时候会让消息顺序打乱,所以还需要设置这个参数:
max.in.flight.requests.per.connection 默认值5,设置为1
10、kafka的文件存储机制
- 同一个topic下,有多个不同的partition,每个partition为一个目录。partition命名的规则是,topic的名称加上一个序号,序号从0开始。
- 每一个partition目录下的文件,被平均切割成大小相等的数据文件(,每一个数据文件都被称为一个段(segment file)
- 每一个segment 段消息,数量不一定相等,使得老的segment可以被快速清除。默认保留7天的数据,每次满1G后,在写入到一个新的文件中。
- 另外每个partition只需要支持顺序读写就可以,也就是说它只会往文件的末尾追加数据,这就是顺序写的过程,生产者只会对每一个partition做数据的追加(写操作)。
11、Segment file是什么
-
生产者生产的消息,按照一定的分区策略,被发送到topic中partition中,
partition在磁盘上就是一个目录,该目录名是topic的名称加上一个序号。
-
在partition目录下,有两类文件,一类是以log为后缀的文件,一类是以index为后缀的文件,每一个log文件和一个index文件相对应,
-
这一对文件就是一个segment file,也就是一个段。
- log文件:就是数据文件,里面存放的就是消息,
- index文件:是索引文件,记录元数据信息。
- 元数据指向,对应的数据文件(log文件)中消息的物理偏移地址。log文件达到1个G后滚动重新生成新的log文件。
segment文件命名的规则:
partition全局的第一个segment从0(20个0)开始,
后续的每一个segment文件名:是上一个segment文件中最后一条消息的offset值。
12、kafka如何保证消息消费的有序性呢?
生产者生产出0到100这100条数据之后,通过一定的分组策略存储到broker的partition中的时候,比如0到10这10条消息被存到了这个partition中,10到20这10条消息被存到了那个partition中,这样的话,消息在分组存到partition中的时候就已经被分组策略搞得无序了。
消费者在消费消息的时候全局有序
1、设置一个partition
一个partition中的数据是有序的吗?回答:间隔有序,不连续。
一个topic里面的数据,只能做到partition内部有序,不能做到全局有序。特别是加入消费者的场景后,如何保证消费者的消费的消息的全局有序性,
这是一个伪命题,只有在一种情况下才能保证消费的消息的全局有序性,那就是只有一个partition。
13、kafka如何快速查询数据
- 索引文件,里面存储的是一对一对的key-value,
- key:是消息在log数据文件中的编号,
- value:是该消息的物理偏移地址(位置)
比如“1,3,6,8……”,分别表示在log文件中的第1条消息、第3条消息、第6条消息、第8条消息……,
索引文件中元数据8,1686为例,其中8代表在右边log数据文件中从上到下第8个消息(在全局partiton表示第368777个消息),其中1686表示该消息的物理偏移地址(位置)为1686。
index文件中,编号不连续,因为,index文件并没有为数据文件中的每条消息都建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。
这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。
但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。
14、Kafka如何不重复消费数据
-
保存并查询
给每个消息都设置一个独一无二的key,消费的时候把这些key记录下来,然后每次消费的时候都查询一下,看这个key是否消费过,如果没有消费过才消费。
-
系统消费消息的业务逻辑,具备幂等性
幂等f(f(x)) = f(x),其任意多次执行所产生的影响均与一次执行的影响相同。
-
为更新的数据,设置前置条件
,给数据变更设置一个前置条件,如果满足条件就更新数据,否则拒绝更新数据,在更新数据的时候,同时变更前置条件中需要判断的数据。
15、Kafka高效文件存储设计特点
- Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
- 通过索引信息可以快速定位message
- 通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
- 通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。
16、为什么Kafka速度那么快
-
磁盘顺序读写
- 磁盘顺序读写,性能要高于,内存的随机读写
- Kafka是将消息记录持久化到本地磁盘,Kafka的message是不断追加到本地磁盘文件末尾的,达到磁盘的顺序读写,而不是随机的写入,这使得Kafka写入吞吐量得到了显著提升
-
Page Cache 系统自身的内存
- Kafka利用操作系统本身的Page Cache(系统自身的内存),而不是JVM空间内存
- 避免Object消耗,如果是使用Java堆内存,Java对象的内存消耗比较大,通常是所存储数据的两倍甚至更多。
- 避免GC问题:随着JVM中数据不断增多,垃圾回收将会变得复杂与缓慢,使用系统缓存就不会存在GC问题。
-
零拷贝(sendfile)
- 减少不必要的拷贝次数,在IO读写过程中,优化消费端
- 数据没有拷贝到用户态,而是直接在核心态就进行了传输
- 使用DMA(Direct Memory Access),直接访问系统主内存,而不用依赖CPU的计算机系统的功能
17、kafka监控工具 kafkaManager
是由雅虎开源的可以监控整个kafka集群相关信息的一个工具。
(1)可以管理几个不同的集群
(2)监控集群的状态(topics, brokers, 副本分布, 分区分布)
(3)创建topic、修改topic相关配置
18、HW&LEO原理
-
LEO(last end offset),日志末端偏移量,
-
标识当前日志文件中,下一条待写入的消息的offset。
-
举一个例子,若LEO=10,那么表示在该副本日志上已经保存了10条消息,位移范围是[0,9]。
-
follower的LEO保存在2个地方
-
follower 所在的broker缓存里。
-
leader 所在broker的缓存里,即leader所在broker的缓存上保存了该分区所有副本的LEO。
-
-
-
HW(High water mark),高水位,
- 标识一个特定的消息偏移量(offset),消费者只能拉取到这个offset之前的消息。
- 任何一个副本对象的HW值,一定不大于其LEO值。
- 小于或等于HW值的所有消息,被认为是“已提交的”或“已备份的”。
- HW主要是用来,判断副本的备份进度.
关系:leader的leo >= follower的leo >= leader保存的follower的leo >= leader的hw >= follower的hw
上面关系反应出各个值的更新逻辑的先后
19、HW&LEO更新机制
-
LEO更新:
-
leader向log写消息时,leader本身的leo更新
-
follower副本 写入一条消息时,leo值会被更新
-
当follower从leader处拉取消息时,leader获取follower的拉取请求中offset参数,leader保存的follower的leo更新
-
-
HW更新:
- leader更新HW的时机
- (1)producer 向 leader 写消息时
(2)leader 处理 follower 的 fetch 请求时
(3)某副本成为leader时
(4)broker 崩溃导致副本被踢出ISR时
- (1)producer 向 leader 写消息时
- follower更新HW,发生在其更新完LEO后,即follower向log写完数据,它就会尝试更新HW值。
- 具体算法:比较当前LEO(已更新)与fetch响应中leader的HW值,取两者的小者作为新的HW值。
- leader更新HW的时机
20、生产者遇到了异常如何处理?
- 添加重试功能和重试时间间隔
- 对于重试也失败了任务进行特殊处理
retry参数:
在kafka中错误分为2种,一种是可恢复的,另一种是不可恢复的。
可恢复性的错误:
如遇到在leader的选举、网络的抖动等这些异常时,如果我们在这个时候配置的retries大于0的,也就是可以进行重试操作,那么等到leader选举完成后、网络稳定后,这些异常就会消息,错误也就可以恢复,数据再次重发时就会正常发送到broker端。需要注意retries(重试)之间的时间间隔,以确保在重试时可恢复性错误都已恢复。
不可恢复性的错误:
如:超过了发送消息的最大值(max.request.size)时,这种错误是不可恢复的,如果不做处理,那么数据就会丢失,因此我们需要注意在发生异常时把这些消息写入到DB、缓存本地文件中等等,把这些不成功的数据记录下来,等错误修复后,再把这些数据发送到broker端。
21、Kafka的ack的三种机制
acks参数,控制发送出去的消息的持久化机制
-
1)如果acks=0,
- producer根本、、不管写入broker的消息到底成功没有,发送一条消息出去,立马就可以发送下一条消息,
- 这是吞吐量最高的方式,但是可能消息都丢失了,你也不知道的,但是说实话
- 实时数据流分析的业务和场景,实时报表,折线图,饼图。
-
2)acks=all,或者acks=-1:
- leader写入成功以后,必须等待其他ISR中的副本都写入成功,才可以返回响应说这条消息写入成功了,此时你会收到一个回调通知。
-
3)acks=1:
- 只要leader写入成功,就认为消息成功了,默认给这个其实就比较合适的,
- 还是可能会导致数据丢失的,如果刚写入leader,leader就挂了,此时数据必然丢了,其他的follower没收到数据副本,变成leader
22、 如何提升生产者的吞吐量?
-
1)设置发送消息的缓冲区,
- buffer.memory:默认值是33554432,就是32MB
- 如果发送消息出去的速度小于写入消息进去的速度,就会导致缓冲区写满,此时生产消息就会阻塞住,所以说这里就应该多做一些压测,尽可能保证说这块缓冲区不会被写满导致生产行为被阻塞住
-
2)设置压缩
- compression.type,默认是none,不压缩,但是也可以使用lz4压缩,效率还是不错的,
- 压缩之后可以减小数据量,提升吞吐量,但是会加大producer端的cpu开销。
-
3)设置batch的大小,
- batch.size,默认值是:16384,就是16kb,也就是一个batch满了16kb就发送出去,一般在实际生产环境,这个batch的值可以增大一些来提升吞吐量,可以自己压测一下。
- 如果batch太小,会导致频繁网络请求,吞吐量下降;如果batch太大,会导致一条消息需要等待很久才能被发送出去,而且会让内存缓冲区有很大压力,过多数据缓冲在内存里
-
4)设置消息的发送延迟
- linger.ms,这个值默认是0,意思就是消息必须立即被发送,但是这是不对的,
- 一般设置一个100毫秒之内的,这样的话就是说,这个消息被发送出去后进入一个batch,如果100毫秒内,这个batch满了16kb,自然就会发送出去。但是如果100毫秒内,batch没满,那么也必须把消息发送出去了,不能让消息的发送延迟时间太长,也避免给内存造成过大的一个压力。
23、如何保证Kafka内部数据不丢失?
如果要回答这个问题的话,要从三个角度去回答:Producer,consumer,broker。
-
producer acks参数、retry参数、
- 1.高可用型
配置:acks = all,retries > 0 retry.backoff.ms=100(毫秒) (并根据实际情况设置retry可能恢复的间隔时间)
优点:这样保证了producer端每发送一条消息都要成功,如果不成功并将消息缓存起来,等异常恢复后再次发送。
缺点:这样保证了高可用,但是这会导致集群的吞吐量不是很高,因为数据发送到broker之后,leader要将数据同步到fllower上,如果网络带宽、不稳定等情况时,ack响应时间会更长 - 2.折中型
配置:acks = 1 retries > 0 retries 时间间隔设置 (并根据实际情况设置retries可能恢复的间隔时间)
优点:保证了消息的可靠性和吞吐量,是个折中的方案
缺点:性能处于2者中间 - 3.高吞吐型
配置:acks = 0
优点:可以相对容忍一些数据的丢失,吞吐量大,可以接收大量请求
缺点:不知道发送的消息是 否成功
- 1.高可用型
-
Consumer group.id auto.offset.reset enable.auto.commit
-
设置consumer group分组的id group.id:如果为空,则会报异常
-
设置从何处开始进行消费 auto.offset.reset = earliest(最早) /latest(最晚)
-
设置是否开启自动提交消费位移的功能,默认开启 enable.auto.commit= true/false(默认true)
-
-
Broker
- 1.replication-factor >=2
在创建topic时会通过replication-factor来创建副本的个数,它提高了kafka的高可用性,同时,它允许n-1台broker挂掉,设置好合理的副本因子对kafka整体性能是非常有帮助的,通常是3个,极限是5个,如果多了也会影响开销。 - 2.min.insync.replicas = 2
分区ISR队列集合中最少有多少个副本,默认值是1 - 3.unclean.leander.election.enable = false
是否允许从ISR队列中选举leader副本,默认值是false,如果设置成true,则可能会造成数据丢失。
- 1.replication-factor >=2
24、 积压了百万消息如何处理?
消息积压的直接原因,一定是系统中的某个部分出现了性能问题,来不及处理上游发送的消息,才会导致消息积压。能导致积压突然增加,原因,只有两种:要么是发送变快了,要么是消费变慢了。
-
最大程度避免消息积压
生产者 提升吞吐量
消费者 扩容,扩分区 增加consumer
-
如何处理消息积压
-
如果是单位时间发送的消息增多,唯一的方法是通过扩容消费端的实例数来提升总体的消费能力。
-
如果短时间内没有足够的服务器资源进行扩容,通过**关闭一些不重要的业务,减少发送方发送的数据量,**最低限度让系统还能正常运转,服务一些重要业务。
-
无论是发送消息的速度还是消费消息的速度和原来都没什么变化,这时候你需要检查一下你的消费端,是不是消费失败导致的一条消息反复消费这种情况比较多,这种情况也会拖慢整个系统的消费速度。
如果监控到消费变慢了,你需要检查你的消费实例,分析一下是什么原因导致消费变慢。优先检查一下日志是否有大量的消费错误,如果没有错误的话,可以通过打印堆栈信息,看一下你的消费线程是不是卡在什么地方不动了,比如触发了死锁或者卡在等待某些资源上了。
-
4、 积压了百万消息如何处理?
消息积压的直接原因,一定是系统中的某个部分出现了性能问题,来不及处理上游发送的消息,才会导致消息积压。能导致积压突然增加,原因,只有两种:要么是发送变快了,要么是消费变慢了。
-
最大程度避免消息积压
生产者 提升吞吐量
消费者 扩容,扩分区 增加consumer
-
如何处理消息积压
-
如果是单位时间发送的消息增多,唯一的方法是通过扩容消费端的实例数来提升总体的消费能力。
-
如果短时间内没有足够的服务器资源进行扩容,通过**关闭一些不重要的业务,减少发送方发送的数据量,**最低限度让系统还能正常运转,服务一些重要业务。
-
无论是发送消息的速度还是消费消息的速度和原来都没什么变化,这时候你需要检查一下你的消费端,是不是消费失败导致的一条消息反复消费这种情况比较多,这种情况也会拖慢整个系统的消费速度。
如果监控到消费变慢了,你需要检查你的消费实例,分析一下是什么原因导致消费变慢。优先检查一下日志是否有大量的消费错误,如果没有错误的话,可以通过打印堆栈信息,看一下你的消费线程是不是卡在什么地方不动了,比如触发了死锁或者卡在等待某些资源上了。
-