0


【架构】Kafka 核心全面总结,高可靠高性能核心原理

引言

在探究 Kafka 核心知识之前,我们先思考一个问题:什么场景会促使我们使用 Kafka? 说到这里,我们头脑中或多或少会蹦出异步解耦和削峰填谷等字样,是的,这就是 Kafka 最重要的落地场景。

异步解耦:同步调用转换成异步消息通知,实现生产者和消费者的解耦。想象一个场景,在商品交易时,在订单创建完成之后,需要触发一系列其他的操作,比如进行用户订单数据的统计、给用户发送短信、给用户发送邮件等等。如果所有操作都采用同步方式实现,将严重影响系统性能。针对此场景,我们可以利用消息中间件解耦订单创建操作和其他后续行为。

削峰填谷:利用 broker 缓冲上游生产者瞬时突发的流量,使消费者消费流量整体平滑。对于发送能力很强的上游系统,如果没有消息中间件的保护,下游系统可能会直接被压垮导致全链路服务雪崩。想象秒杀业务场景,上游业务发起下单请求,下游业务执行秒杀业务(库存检查,库存冻结,余额冻结,生成订单等等),下游业务处理的逻辑是相当复杂的,并发能力有限,如果上游服务不做限流策略,瞬时可能把下游服务压垮。针对此场景,我们可以利用 MQ 来做削峰填谷,让高峰流量填充低谷空闲资源,达到系统资源的合理利用。

通过上述例子可以发现交易、支付等场景常需要异步解耦和削峰填谷功能解决问题,而交易、支付等场景对性能、可靠性要求特别高。那么,我们本文的主角 Kafka 能否满足相应要求呢?下面我们来探讨下。

Kafka 宏观认知

在探究 Kafka 的高性能、高可靠性之前,我们从宏观上来看下 Kafka 的系统架构:

图片

如上图所示,Kafka 由 Producer、Broker、Consumer 以及负责集群管理的 ZooKeeper 组成,各部分功能如下:

  • Producer:生产者,负责消息的创建并通过一定的路由策略发送消息到合适的 Broker;
  • Broker:服务实例,负责消息的持久化、中转等功能;
  • Consumer :消费者,负责从 Broker 中拉取(Pull)订阅的消息并进行消费,通常多个消费者构成一个分组,消息只能被同组中的一个消费者消费;
  • ZooKeeper:负责 broker、consumer 集群元数据的管理等;(注意:Producer 端直接连接 broker,不在 zk 上存任何数据,只是通过 ZK 监听 broker 和 topic 等信息)

上图消息流转过程中,还有几个特别重要的概念—主题(Topic)、分区(Partition)、分段(segment)、位移(offset)。

  • topic:消息主题。Kafka 按 topic 对消息进行分类,我们在收发消息时只需指定 topic。
  • partition:分区。为了提升系统的吞吐,一个 topic 下通常有多个 partition,partition 分布在不同的 Broker 上,用于存储 topic 的消息,这使 Kafka 可以在多台机器上处理、存储消息,给 kafka 提供给了并行的消息处理能力和横向扩容能力。另外,为了提升系统的可靠性,partition 通常会分组,且每组有一个主 partition、多个副本 partition,且分布在不同的 broker 上,从而起到容灾的作用。
  • segment:分段。宏观上看,一个 partition 对应一个日志(Log)。由于生产者生产的消息会不断追加到 log 文件末尾,为防止 log 文件过大导致数据检索效率低下,Kafka 采取了分段和索引机制,将每个 partition 分为多个 segment,同时也便于消息的维护和清理。每个 segment 包含一个.log 日志文件、两个索引(.index、timeindex)文件以及其他可能的文件。每个 Segment 的数据文件以该段中最小的 offset 为文件名,当查找 offset 的 Message 的时候,通过二分查找快找到 Message 所处于的 Segment 中。
  • offset:消息在日志中的位置,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量。offset 是消息在分区中的唯一标识,是一个单调递增且不变的值。Kafka 通过它来保证消息在分区内的顺序性,不过 offset 并不跨越分区,也就是说,Kafka 保证的是分区有序而不是主题有序。

Kafka 高可靠性、高性能探究

在对 Kafka 的整体系统框架及相关概念简单了解后,下面我们来进一步深入探讨下高可靠性、高性能实现原理。

Kafka 高可靠性探究

Kafka 高可靠性的核心是保证消息在传递过程中不丢失,涉及如下核心环节:

  • 消息从生产者可靠地发送至 Broker;-- 网络、本地丢数据;
  • 发送到 Broker 的消息可靠持久化;-- Pagecache 缓存落盘、单点崩溃、主从同步跨网络;
  • 消费者从 Broker 消费到消息且最好只消费一次 -- 跨网络消息传输 。
消息从生产者可靠地发送至 Broker

为了保障消息从生产者可靠地发送至 Broker,我们需要确保两点;

  1. Producer 发送消息后,能够收到来自 Broker 的消息保存成功 ack;
  2. Producer 发送消息后,能够捕获超时、失败 ack 等异常 ack 并做处理。
ack 策略

针对问题 1,Kafka 为我们提供了三种 ack 策略,

  • Request.required.acks = 0:请求发送即认为成功,不关心有没有写成功,常用于日志进行分析场景;
  • Request.required.acks = 1:当 leader partition 写入成功以后,才算写入成功,有丢数据的可能;
  • Request.required.acks= -1:ISR 列表里面的所有副本都写完以后,这条消息才算写入成功,强可靠性保证;

为了实现强可靠的 kafka 系统,我们需要设置 Request.required.acks= -1,同时还会设置集群中处于正常同步状态的副本 follower 数量 min.insync.replicas>2,另外,设置 unclean.leader.election.enable=false 使得集群中 ISR 的 follower 才可变成新的 leader,避免特殊情况下消息截断的出现。

消息发送策略

针对问题 2,kafka 提供两类消息发送方式:同步(sync)发送和异步(async)发送,相关参数如下:

图片

以 sarama 实现为例,在消

标签: 架构 kafka 分布式

本文转载自: https://blog.csdn.net/wjianwei666/article/details/136162973
版权归原作者 奔向理想的星辰大海 所有, 如有侵权,请联系我们删除。

“【架构】Kafka 核心全面总结,高可靠高性能核心原理”的评论:

还没有评论