本书未发布

Kafka特性

未匹配的标注

框架:概念,消费者,生产者,配置,监控,特性,集群,调优

概念

消息:Record。Kafka 是消息引擎嘛,这里的消息就是指 Kafka 处理的主要对象。
主题:Topic。主题是承载消息的逻辑容器,在实际使用中多用来区分具体的业务。
分区:Partition。一个有序不变的消息序列。每个主题下可以有多个分区。
消息位移:Offset。表示分区中每条消息的位置信息,是一个单调递增且不变的值。
副本:Replica。Kafka 中同一条消息能够被拷贝到多个地方以提供数据冗余,这些地方就是所谓的副本。副本还分为领导者副本和追随者副本,各自有不同的角色划分。副本是在分区层级下的,即每个分区可配置多个副本实现高可用。
生产者:Producer。向主题发布新消息的应用程序。
消费者:Consumer。从主题订阅新消息的应用程序。
消费者位移:Consumer Offset。表征消费者消费进度,每个消费者都有自己的消费者位移。
消费者组:Consumer Group。多个消费者实例共同组成的一个组,同时消费多个分区以实现高吞吐。
重平衡:Rebalance。消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。Rebalance 是 Kafka 消费者端实现高可用的重要手段。

生产者和消费者

生产者生产消息

一个生产者如果只对应一个消费者,可以这样设计:
Kafka特性

在kafka中:
客户端:生产者,消费者
服务端:Broken

生产者可以通过Topic发布消息到多个分区,消费者可以从不同的Broken订阅Topic,从而达到负载均衡。

Kafka特性

在分区中,每个消息实体都是唯一标识的。通过消息位移的方式消费分区中的消息实体。

Kafka特性

分区策略:轮训策略/随机策略/按消息键保序策略/基于地理位置的分区策略/

轮询策略:
Kafka特性

随机策略:
Kafka特性

按消息键保序策略:
Kafka特性

消费者组

消费引擎模型:点对点模型(消息队列),发布/订阅模型。消息队列特性—消息队列模型多个消费者争抢一个消息实例,消息被消费后则从队列中删除。这不是缺陷,只是特性。发布/订阅模型特性—一个消息允许被多个消费者消费,不足之处是消费者需要订阅所有的分区。
伸缩性很差。差在哪里呢?(RabbitMQ的消费者我记得就是消息队列模型)。作者的意思是:Kafka消息组同时实现了消息引擎两个模型的特点—一个分区只有一个组的消费者实例,则认为是消息队列模型。一个分区有多个组的消费者实例,则认为是发布/订阅模型。
而且消费组不需要订阅所有的分区。
一个主题分区需要几个消费者呢?Kafka建议的是一个。如果分区数多于消费者数一个消费者可能对应多个分区,如果分区数小于消费者数,则有消费者会空闲。

这个不是应该还要考虑消费者的消费速度吗?如果消费速度快,一对一已经满足那么这个方案是适合的。如果一对一消费者消费速度慢,导致消息可能积压。这种情况应该是多个消费者更好。在RabbitMQ中可以估算一个消息的消费速度决定要多少个消费者。

思考题

  1. 为什么使用分区的概念而不是直接使用多个主题呢?

  2. Kafka 消息交付可靠性保障以及精确处理一次语义的实现。

    所谓的可靠性交付,是Kafka对生产者和消费者的承诺:

    1. 最多一次:消息可能会丢失,但是绝对不会重复消费。
      》只需要禁止Productor重发即可,这样消息要么发送成功,要么发送失败。
    2. 最少一次:消息可能会重复消费,但是绝对不会丢失。(默认)
      》Productor接收到Broken的ack才认为消息发送成功,倘若网络抖动导致Productor没有接收到,则Productor会重发。
    3. 精确一次:消息不会重复消费,也不会丢失。
      》通过两种机制:幂等性和事务。

那Kafka是如何实现的呢?已经可以保证精确一次了,为什么还要其他的承诺呢?

个人猜测先:不同的实现性能消耗不一样。如最多一次速度更优,无需接收Broken的ACK。最少一次需要接收Broken的ACK并且可能重发。而精确一次则需要保证幂等性和事务,性能消耗和速度会更差。
不同的承诺对应的业务场景不同:最多一次—如日志采集,丢失一些数据是可以接受的,保证速度优先。最少一次—某些业务会自己保证幂等性,但是不允许数据的丢失。如钱包业务。精确一次—通过Kafka保证了幂等性,在业务侧则无需保证幂等性。
个人认为第二种更好点:一般业务都会自己处理幂等性,不会把所有的期望都寄托于Kafka的实现。

  1. 聊聊Kafka的幂等性和事务

    幂等性:
    Kafka为了实现幂等性,它在底层设计架构中引入了ProducerID和SequenceNumber。
    ProducerID:在每个新的Producer初始化时,会被分配一个唯一的ProducerID,这个ProducerID对客户端使用者是不可见的。
    SequenceNumber:对于每个ProducerID,Producer发送数据的每个Topic和Partition都对应一个从0开始单调递增的SequenceNumber值。
    》Kafka通过空间换时间的方式,对每个消息都做了标志。如果消息重复发送,Kafka会自动识别并丢弃。
    》但是这个幂等性只能作用于单个分区和单次会话,如果Topic分布在多个分区,或者是不同的会话在发布消息Kafka是无法保证幂等性的。

为了解决幂等性的不足,事务型Productor就出现了!那么他又是怎么实现的呢?

事务:开启幂等性和事务,并设置隔离级别为read_committed。
》如MySQL的事务ACID。C是隔离级别,不同的数据库实现对应的隔离级别定义不同,如不可提交读,提交读,可重复读,串行读写。Kafka的事务隔离级别是提交读。

  1. read_uncommitted:这是默认值,表明 Consumer 能够读取到 Kafka 写入的任何消息,不论事务型 Producer 提交事务还是终止事务,其写入的消息都可以读取。很显然,如果你用了事务型 Producer,那么对应的 Consumer 就不要使用这个值。
  2. read_committed:表明 Consumer 只会读取事务型 Producer 成功提交事务写入的消息。当然了,它也能看到非事务型 Producer 写入的所有消息。
  1. 现在,请你尝试用 3 个副本来说明一下副本同步全流程,以及分区高水位被更新的过程。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~