《深入理解kafka》对于实际问题的理解

发布于:2024-05-10 ⋅ 阅读:(32) ⋅ 点赞:(0)

Q1:消息可靠性(不重不漏)

1.1 如何保证消息不丢

1.2 如何保证消息不重

Q2:积压/消费能力

2.1 线上积压排查思路

2.2 增加消费能力

Q1:消息可靠性(不重不漏)

理解可靠性前。介绍消息语义,即消息传递的标准

标准

丢失

重复

适用场景

At most once(至多一次)

会丢失

不会重复

高并发高吞吐,允许消息丢失,如日志收集

At least once(至少一次)

不会丢失

会重复

Exactly once(恰好一次)

不会丢失

不会重复

1.1 如何保证消息不丢

从各个层面分析

  • 参照:​《深入理解kafka-核心设计与实践原理》​第8.3章 + 自己理解

层面

事项

生产者(客户端)

  • 代码发送层面

    • ①发送消息Api的三种模式:发后即忘、同步和异步。发后即忘会丢失消息,后两者能知道是否发送成功

    • ②补发消息机制:客户端持久化消息,支持消息的补偿

  • 配置层面

    • ③生产者客户端参数(acks参数):acks= -1最可靠,其余两种都可能会丢失消息

    • ④重试参数(retries参数和retry.backoff.ms参数):对于可重试的异常(如网络抖动),通过失败重试机制重发消息

Broker服务端

服务端需要注意的都是配置参数层面

  • ①副本数(replication.factor参数) > 1

    • 越多的副本数越能够保证数据的可靠性,但副本太多会影响性能。应对宕机风险,通常设置为3就能满足大多数场景

  • ②ISR集合中的最小副本数(min.insync.replicas参数) >1

    • 用于辅助配合acks=-1来使用:leader副本的消息流入速度很快,而follower副本的同步速度很慢。在某个临界点时所有的follower副本都被剔除出了ISR集合,那么ISR最终只剩一个leader副本,导致acks=-1演变为acks=1的情形

    • 该值必须小于副本数,一个典型的配置是:replication.factor=3,min.insync.replicas=2

  • ③是否允许从非ISR中选举新leader(unclean.leader.election.enable参数) = false:默认为false,不允许

    • 非ISR集合中,可能还未同步所有消息,设置成true会造成消息丢失

  • 其他:log.flush.interval.messages和log.flush.interval.ms,是否开启同步刷盘(默认是不做控制而交由操作系统本身来进行处理)

    • 可能性分析:由于刷盘是操作系统控制,理论上讲会存在即使kafka写入成功,但由于机器宕机,操作系统未及时刷盘,丢失数据的风险

    • 但同步刷盘非常损耗性能,改成每次提交时手动同步刷盘对性能影响太大。这里不建议修改此配置,因为发生可能性很小

消费者(客户端)

①自动提交(enable.auto.commit参数) = false:默认为true,自动提交。不再介绍,见3.2.5节

  • 自动提交会带来重复消费和消息丢失的问题:消费者还未执行完业务流程,异步线程已对服务端发起了提交

  • 手动提交需遵守一个原则:如没有消费完,则不能提交

1.2 如何保证消息不重

消息重复无法避免,只能在消费者消费时过滤重复消息。可能的重复原因如下:

根因

生产者

业务方代码原因:对同一份消息内容发送了多次

网络问题:生产端发送消息后,服务端已经收到消息了,但是假如遇到网络问题,无法获得响应,生产端就无法判断该消息是否成功提交到了 Kafka,而我们一般会配置重试次数,但这样会引发生产端重新发送同一条消息,从而造成消息重复的发送

Broker服务端

服务端不会重复存储消息,如果有重复消息也应该是由生产端重复发送造成的

消费者

分区重分配引起

  • 在客户端实例变化、分区扩容、集群切换等场景会涉及到分区重分配,由于新老客户端感知分配结果不及时,可能出现两台机器短时间消费同一个分区的场景,造成重复消费

备注:分区重分配,与再均衡(rebalance)的区别

  • 重分配:作用在broker层面,是broker与partition间的分配;通常是为了管理优化集群手动触发
  • 再平衡:作用在消费组层面(新增/下线消费者),Rebalance的目的是确保分区在consumer group成员之间平均分配,以便每个consumer都有分区去消费;通常是Kafka协调器自动触发的

处理思路:幂等

从对系统的影响结果来说:At least once + 幂等消费 = Exactly once。

  1. 利用数据库的唯一约束实现幂等

  2. 记录消费结果并检查操作

Q2:积压/消费能力

2.1 线上积压排查思路

是什么引起的积压:

  • 先止损,快速定位积压的原因

    • 上游生产流量突增

    • 上游流量没变

      • 不消费了:

        • 消费者是否下线了?

        • 某一个partition的offset卡住了?

      • 还在消费:消费能力下降?

2.2 增加消费能力

搞清原因:什么导致【消费速率 < 生产速率】

生产速率

可能原因

解决方案

备注

生产速率不高

自身业务消费链路长,导致消费慢

优化消费链路

绝大多数情况

生产速率高

①消费者实例 < partition数量。一台机器消费多个partition的情况,并且机器负载较高

扩集群机器,一直到【消费者:partition=1:1】

影响可控

②消费者实例:partition = 1:1,但消费速率仍小于生产速率

扩partition。但一未扩partition会增加服务端负载

③partition本身已很多,但生产速率实在太大

增加单partiton并行消费线程数目(这种方式不保证消费顺序!!!

  • mafka和rocketmq支持,kafka与rabbitmq不支持

  • 总体思路:滑动窗口

是不是该考虑架构与技术选型的问题了?

④生产速率实在太大了

pushServer


网站公告

今日签到

点亮在社区的每一天
去签到