【大数据】kafka 线上会遇到哪些问题?

1.如何保证 Kafka 中的消息是有序的?

单线程顺序消费

生产者在发送消息时,将消息对应的id进行取模处理,相同的id发送到相同的分区。消息在分区内有序,一个分区对应了一个消费者,保证了消息消费的顺序性。

多线程顺序消费

单线程顺序消费已经解决了顺序消费的问题,但是它的扩展能力很差。为了提升消费者的处理速度,但又要保证顺序性,我们只能横向扩展分区数,增加消费者。
我们可以模仿一下kafka的分区思想操作。将接收到的kafka数据进行hash取模(注意注意,你kafka分区接受消息已经是取模的了,这里一定要对id做一次hash再取模)发送到不同的队列,然后我们开启多个线程去消费对应队列里面的数据。

2.如何保证Kafka数据的一致性

kafka是通过HW(High Water Mark) 机制来保证数据的一致性。

image.png

(1)follower故障
follower发生故障后会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步。等该follower的LEO大于等于该Partition的HW,即follower追上leader之后,就可以重新加入ISR了。

(2)leader故障
leader发生故障之后,会从ISR中选出一个新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据。

3.Kafka会在哪些场景出现重复消费,为什么

导致Kafka消息重复消费有以下两个原因:
1.Kafka消息重复提交导致消息重复消费
默认情况下,消息消费完后,会自动提交Offset的值,避免重复消费。Kafka消费端的自动提交,会有一个默认5秒的间隔,在5秒之后的下一次向Broker拉取消息的时候才提交上一批消费的offset。如果在消费过程中,如果遇到应用程序被强制kill掉,就会导致Offset没有及时提交,导致消息重复消费。(消费者宕机造成重复消费)
2.Kafka服务端的Partition在均衡机制导致消息重复消费。
在Kafka服务端的Partition再均衡机制导致消息重复消费,会把多个Partition均衡的分配给多个消费者,消费者会从分配的partition里面去消费消息,如果消费者在默认的5分钟内没有去处理完这批消息的话就会触发kafka的reblance机制。从而导致offset自动提交失败。而Rebalance之后,消费者还会从之前没有提交的offset位置开始消费,从而导致消息重复消费。(1.session超时造成重复消费 2.处理能力弱造成重复消费)
解决重复消费消息的问题有以下方法:

1.提高消费端处理性能避免触发Balance
用多线程的方式处理消息,缩短单个消息消费的时长。
调整消息处理的超时时间
减少一次性从Broker上拉取数据的条数。
2.使用ConsumerRebalanceListener,再均衡监听器
用来设定发生再均衡动作前后的一些准备或者收尾工作。
3.使用消息幂等性
将消息生成的唯一id保存到mysql或者redis中,再处理消息之前先查mysql或者redis,判断是否已经消费过。

4.谈谈Kafka线上大量消息积压你是如何处理的?

如果是 Kafka 消费能力不足,则可以考虑增加 Topic 的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。 (两者缺一不可)
如果是下游的数据处理不及时: 提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度) ,使处理的数据小于生产的数据,也会造成数据积压
**消息大量积压这个问题,直接原因一定是某个环节出现了性能问题,来不及消费消息,才会导致消息积压。**接着就比较坑爹了,此时假如 Kafka 集群的磁盘都快写满了,都没有被消费,这个时候怎么办?或者消息积压了⼏个⼩时,这个时候怎么办?生产环境挺常⻅的问题,⼀般不出问题,而⼀出就是⼤事故。

所以,我们先来分析下,在使用 Kafka 时如何来优化代码的性能,避免出现消息积压。如果你的线上 Kafka 系统出现了消息积压,该如何进行紧急处理,最大程度地避免消息积压对业务的影响。

01 优化性能来避免消息积压

对于 Kafka 性能的优化,主要体现在生产者和消费者这两部分业务逻辑中。而 Kafka 本身不需要多关注的主要原因是,对于绝大多数使用Kafka 的业务来说,Kafka 本身的处理能力要远大于业务系统的处理能力。Kafka 单个节点,消息收发的性能可以达到每秒钟处理几十万条消息的水平,还可以通过水平扩展 Broker 的实例数成倍地提升处理能力。

对于业务系统处理的业务逻辑要复杂一些,单个节点每秒钟处理几百到几千次请求,已经非常不错了,所以我们应该更关注的是消息的收发两端。

**1. 发送端性能优化

**
发送端即生产者业务代码都是先执行自己的业务逻辑,最后再发送消息。如果说性能上不去,需要你优先检查一下,是不是发消息之前的业务逻辑耗时太多导致的

对于发送消息的业务逻辑,只需要注意设置合适的并发和批量大小,就可以达到很好的发送性能。我们知道 Producer 发消息给 Broker 且收到消息并返回 ack 响应,假设这一次过程的平均时延是 1ms,它包括了下面这些步骤的耗时:
1)发送端在发送网络请求之前的耗时。
2)发送消息和返回响应在网络传输中的耗时。
3)Broker 端处理消息的时延。
假设此时你的发送端是单线程,每次只能发送 1 条消息,那么每秒只能发送 1000 条消息,这种情况下并不能发挥出 Kafka 的真实性能。此时无论是增加每次发送消息的批量大小,还是增加并发,都可以成倍地提升发送性能。
如果当前发送端是在线服务的话,比较在意请求响应时延,此时可以采用并发方式来提升性能。
如果当前发送端是离线服务的话,更关注系统的吞吐量,发送数据一般都来自数据库,此时更适合批量读取,批量发送来提升性能。
另外还需要关注下消息体是否过大,如果消息体过大,势必会增加 IO 的耗时,影响 Kafka 生产和消费的速度,也可能会造成消息积压。
**

**2. 消费端性能优化

**
而在使用 Kafka 时,大部分的性能问题都出现在消费端,如果消费的速度跟不上发送端生产消息的速度,就会造成消息积压。如果只是暂时的,那问题不大,只要消费端的性能恢复之后,超过发送端的性能,那积压的消息是可以逐渐被消化掉的。
要是消费速度一直比生产速度慢,时间长了系统就会出现问题,比如Kafka 的磁盘存储被写满无法提供服务,或者消息丢失,对于整个系统来说都是严重故障。
所以我们在设计的时候,一定要保证消费端的消费性能要高于生产端的发送性能,这样的系统才能健康的持续运行。
消费端的性能优化除了优化业务逻辑外,也可以通过水平扩容,增加消费端的并发数来提升总体的消费性能。需要注意的是,在扩容 Consumer 的实例数量的同时,必须同步扩容主题中的分区数量,确保 Consumer 的实例数和分区数量是相等的,如果 Consumer 的实例数量超过分区数量,这样的扩容实际上是没有效果的

消息积压后如何处理

日常系统正常时候,没有积压或者只有少量积压很快就消费掉了,但某时刻,突然开始积压消息且持续上涨。这种情况下需要你在短时间内找到消息积压的原因,迅速解决问题。

导致消息积压突然增加,只有两种:发送变快了或者消费变慢了。

假如赶上大促或者抢购时,短时间内不太可能优化消费端的代码来提升消费性能,此时唯一的办法是通过扩容消费端的实例数来提升总体的消费能力。如果短时间内没有足够的服务器资源进行扩容,只能降级一些不重要的业务,减少发送方发送的数据量,最低限度让系统还能正常运转,保证重要业务服务正常。
假如通过内部监控到消费变慢了,需要你检查消费实例,分析一下是什么原因导致消费变慢?

1、优先查看日志是否有大量的消费错误。
2、此时如果没有错误的话,可以通过打印堆栈信息,看一下你的消费线程是不是卡在哪里「触发死锁或者卡在某些等待资源」。

5.kafka数据丢失问题,及如何保证?

1)数据丢失:

消息生产者:

(1)acks=0:表示producer不需要等待任何broker确认收到消息的回复,就可以继续发送下一条消息。性能最高,但是最容易丢消 息。大数据统计报表场景,对性能要求很高,对数据丢失不敏感的情况可以用这种。
(2)acks=1:至少要等待leader已经成功将数据写入本地log,但是不需要等待所有follower是否成功写入。就可以继续发送下一条消 息。这种情况下,如果follower没有成功备份数据,而此时leader又挂掉,则消息会丢失。
(3)acks=-1或all:这意味着leader需要等待所有备份(min.insync.replicas配置的备份个数)都成功写入日志,这种策略会保证只要有一 个备份存活就不会丢失数据。这是最强的数据保证。一般除非是金融级别,或跟钱打交道的场景才会使用这种配置。当然如果 min.insync.replicas配置的是1则也可能丢消息,跟acks=1情况类似。

消息消费端:

如果消费这边配置的是自动提交,万一消费到数据还没处理完,就自动提交offset了,但是此时你consumer直接宕机了,未处理完的数据 丢失了,下次也消费不到了。

2)解决方法:

1)brocker如何保证不丢失:

不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。记住,一定要使用带有回调通知的 send 方法。
acks=-1 : 所有副本都写入成功并确认
设置 retries 为一个较大的值。这里的 retries 同样是 Producer 的参数,对应前面提到的 Producer 自动重试。当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了 retries > 0 的 Producer 能够自动重试消息发送,避免消息丢失。
设置 min.insync.replicas > 1。这依然是 Broker 端参数,控制的是消息至少要被写入到多少个副本才算是“已提交”。设置成大于 1 可以提升消息持久性。在实际环境中千万不要使用默认值 1。
设置 unclean.leader.election.enable = false。这是 Broker 端的参数,它控制的是哪些 Broker 有资格竞选分区的 Leader。如果一个 Broker 落后原先的 Leader 太多,那么它一旦成为新的 Leader,必然会造成消息的丢失。故一般都要将该参数设置成 false,即不允许这种情况的发生。
设置 replication.factor >= 3。这也是 Broker 端的参数。其实这里想表述的是,最好将消息多保存几份,毕竟目前防止消息丢失的主要机制就是冗余。
确保 replication.factor > min.insync.replicas。如果两者相等,那么只要有一个副本挂机,整个分区就无法正常工作了。我们不仅要改善消息的持久性,防止数据丢失,还要在不降低可用性的基础上完成。推荐设置成 replication.factor = min.insync.replicas + 1。

2)Consumer如何保证不丢失:

确保消息消费完成再提交。Consumer 端有个参数 enable.auto.commit,最好把它设置成 false,并采用手动提交位移的方式。就像前面说的,这对于单 Consumer 多线程处理的场景而言是至关重要的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏书QAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值