Kafka 阶段性总结
一)业务场景中,我们会碰到哪些模型?
1.1 场景一 :我就注销了一个商户
背景
:商服 是一个维护商户基本信息的平台系统。
场景
:当商户进行了销户行为后,如果其他的业务部门进行感知到这个变化,商服需要怎么做?
思考
: 最简单的办法,由业务部门提供接口,商服对接,并在处置完销户行为后,调用该接口。
问题
:
-
业务部门对接一次,回头业务部门B也要感知到销户,再对接一次?
-
业务部门今天要感知销户,明天要感知新商户注册,你商服重新对接不对接?
结果除了造成人力告罄外,还需要考虑接了N个业务部门后,如何保证时耗、成功率等引申出来的问题。
1.2 场景二 :xxx , 我这是主库 ,你们怎么还在轮询 ?
背景
: A系统向B系统创建一发支付单,B系统同步告知A系统订单状态为「支付中」。
场景
: A系统在订单支付完成后,去推动后续业务执行,但是只有B系统才知道是否支付完成。
行动
:
N0: A --query–> B , 支付完成了吗?
N1: A --query–> B , 支付完成了?
N2: A --query–> B , 支付完成?
N3: A --query–> B , 支付完?
N4: A --query–> B , 支付?
N4: A --query–> B , 支?B : 别查了,资源告罄了…
思考
:
A 系统很委屈,我又不知道查询的步长,我怎么知道什么频率查询是合适的?
B 系统很憋屈,这种实时性的东西又做不了读写,资源全都被浪费了。
1.3 场景三 :消除峰值
对不起,我们业务没有峰值可消,流量是均匀的…
偶尔做一次活动,系统会直接被打死的呢种…
二)我们脑海中的Kafka
2.1 消息队列的出现解决了什么?
- 数据持久化,数据缓冲,异步通信。保证数据不丢失,通过缓冲层来帮助任务最高效率的执行,可存储大量历史数据可以异步处理。
- 扩展性,解耦处理过程。增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。
- 灵活性,峰值处理能力。不会因为突发的超负荷的请求而完全崩溃。
- 可恢复性。系统的一部分组件失效时,不会影响到整个系统。加入队列中的消息仍然可以在系统恢复后被处理。
- 时序性。在大多使用场景下,数据处理的顺序都很重要。
2.2 呢为什么是kafka?
- KAFKA比较成熟,并且以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间复杂度的访问性能。
- 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条以上消息的传输。顺序写磁盘(顺序写磁盘效率比随机写内存要高,保障 kafka 吞吐率。
- 支持Kafka Server间的消息分区,及分布式消费,同时保证每个Partition内的消息顺序传输,采用消息的批量处理,zero-copy机制。
- 同时支持离线数据处理和实时数据处理。
- 支持在线水平扩展,随时增加zookeeper节点,每个broker还可以分布在不同磁盘,增加处理性能
与其他消息队列的对比:
三)Kafka入门介绍
最最最最基础的概念:
Producer 生产者
,采用Push方式进行消息发布生产。 Producer可以通过与zookeeper连接获取broker信息, topic信息等等元数据,然后再与broker交互进行消息发布。
Consumer 消费者
,采用Pull方式,从Broker端拉取消息并进行处理。当采用订阅方式订阅感兴趣的Topic时,Consumer必须属于一个消费分组,而且Kafka保证同一个Topic的一条消息只能被同一个消费分组(GroupId)中的一个Consumer消费,但多个消费分组可以同时消费这一条消息。
Broker
,消息缓存代理,Kafka集群包含一个或多个服务器,这些服务器被称为Broker,负责消息的存储于转发,作为代理对外提供生产和消费服务。
我用什么方法把消息传输出去?
点对点模型
:也叫消息队列模型。系统 A 发送的消息只能被系统 B 接收,其他任何系统都不能读取 A 发送的消息。日常生活的例子比如电话客服就属于这种模型:同一个客户呼入电话只能被一位客服人员处理,第二个客服人员不能为该客户服务。
发布 / 订阅模型
:与上面不同的是,它有一个主题(Topic)的概念,你可以理解成逻辑语义相近的消息容器。该模型也有发送方和接收方,只不过提法不同。发送方也称为发布者(Publisher),接收方称为订阅者(Subscriber)。和点对点模型不同的是,这个模型可能存在多个发布者向相同的主题发送消息,而订阅者也可能存在多个,它们都能接收到相同主题的消息。生活中的报纸订阅就是一种典型的发布 / 订阅模型。
四)Kafka的HA与Scalability
Kafka的高可用(HA)与伸缩性(Scalability)是怎么处理的呢 ? 毕竟谁也无法保证节点不宕机,更无法保证数据量不会增长。呢难道碰到这样的场景,只能自求多福咯?
4.1 HA
- Broker分散部署
- 备份机制(Replication)
Broker分散部署
:
一个 Kafka 集群由多个 Broker 组成,Broker 负责接收和处理客户端发送过来的请求,以及对消息进行持久化。虽然多个 Broker 进程能够运行在同一台机器上,但更常见的做法是将不同的 Broker 分散运行在不同的机器上,这样如果集群中某一台机器宕机,即使在它上面运行的所有 Broker 进程都挂掉了,其他机器上的 Broker 也依然能够对外提供服务。这其实就是 Kafka 提供高可用的手段之一,Kafka天然就支持分布式。
如果对kafka比较陌生,呢关于broker到底是什么,你应该是有疑问的。
在这里我建议你先理解成 broker是一个进程 ,Kafka在每台机器上启动的自己的一个进程。
备份机制
:
实现高可用的另一个手段就是备份机制(Replication)。备份的思想很简单,就是把相同的数据拷贝到多台机器上,而这些相同的数据拷贝在 Kafka 中被称为副本(Replica)。
比如mysql主备 、 redis 一主多从 ;
呢么kafka能像 MySQL 的从库呢样,令从库可以处理读操作吗?要回答这个问题,我们需要引入几个概念;
名称 | 解释 |
---|---|
Replication | 可以理解为topic消息的副本,隶属于Partition。 |
Leader | replica 中的一个角色, producer 和 consumer 只跟 leader 交互。 |
Follower | replica 中的一个角色,从 leader 中复制数据。 |
Kafka 定义了两类副本:领导者副本(Leader Replica)和追随者副本(Follower Replica)。前者对外提供服务,这里的对外指的是与客户端程序进行交互;而后者只是被动地追随领导者副本而已,不能与外界进行交互,
在 Kafka 中追随者副本不会对外提供服务。
副本的数据流向
Kafka 的副本机制比其他分布式系统要更严格一些。在 Kafka 中,追随者副本是不对外提供服务的。这就是说,任何一个追随者副本都不能响应消费者和生产者的读写请求。所有的请求都必须由领导者副本来处理,或者说,所有的读写请求都必须发往领导者副本所在的 Broker,由该 Broker 负责处理。追随者副本不处理客户端请求,它唯一的任务就是从领导者副本异步拉取消息,并写入到自己的提交日志中,从而实现与领导者副本的同步。
-
方便实现“Read-your-writes”
。所谓 Read-your-writes,顾名思义就是,当你使用生产者 API 向 Kafka 成功写入消息后,马上使用消费者 API 去读取刚才生产的消息。举个例子,比如你平时发微博时,你发完一条微博,肯定是希望能立即看到的,这就是典型的 Read-your-writes 场景。如果允许追随者副本对外提供服务,由于副本同步是异步的,因此有可能出现追随者副本还没有从领导者副本那里拉取到最新的消息,从而使得客户端看不到最新写入的消息。 -
方便实现单调读(Monotonic Reads)
。什么是单调读呢?就是对于一个消费者用户而言,在多次消费消息时,它不会看到某条消息一会儿存在一会儿不存在。如果允许追随者副本提供读服务,那么假设当前有 2 个追随者副本 F1 和 F2,它们异步地拉取领导者副本数据。倘若 F1 拉取了 Leader 的最新消息而 F2 还未及时拉取,那么,此时如果有一个消费者先从 F1 读取消息之后又从 F2 拉取消息,它可能会看到这样的现象:第一次消费时看到的最新消息在第二次消费时不见了,这就不是单调读一致性。但是,如果所有的读请求都是由 Leader 来处理,那么 Kafka 就很容易实现单调读一致性。
4.2 Scalability
虽然有了副本机制可以保证数据的持久化或消息不丢失,但没有解决伸缩性的问题。伸缩性即所谓的 Scalability,是分布式系统中非常重要且必须要谨慎对待的问题。什么是伸缩性呢?我们拿副本来说,虽然现在有了领导者副本和追随者副本,但倘若领导者副本积累了太多的数据以至于单台 Broker 机器都无法容纳了,此时应该怎么办呢?一个很自然的想法就是,能否把数据分割成多份保存在不同的 Broker 上?如果你就是这么想的,那么恭喜你,Kafka 就是这么设计的。
这种机制就是所谓的分区(Partitioning)。如果你了解其他分布式系统,你可能听说过分片、分区域等提法,比如 MongoDB 和 Elasticsearch 中的 Sharding、HBase 中的 Region,其实它们都是相同的原理,只是 Partitioning 是最标准的名称。
Kafka 中的分区机制指的是将每个主题划分成多个分区(Partition),每个分区是一组有序的消息日志。生产者生产的每条消息只会被发送到一个分区中,也就是说如果向一个双分区的主题发送一条消息,这条消息要么在分区 0 中,要么在分区 1 中。如你所见,Kafka 的分区编号是从 0 开始的,如果 Topic 有 100 个分区,那么它们的分区号就是从 0 到 99。
4.2 Replication与Partition的联系
刚才提到的副本如何与这里的分区联系在一起呢?实际上,副本是在分区这个层级定义的。
每个分区下可以配置若干个副本,其中只能有 1 个领导者副本和 N-1 个追随者副本。
生产者向分区写入消息,每条消息在分区中的位置信息由一个叫位移(Offset)的数据来表征。
分区位移总是从 0 开始,假设一个生产者向一个空分区写入了 10 条消息,那么这 10 条消息的位移依次是 0、1、2、…、9。
五)总结
至此,再次回忆了一波Kafka中的基础概念,随后继续阅读似懂非懂的生产者代码 - - 。