Kafka 基础概念

一、设计理念

1.0.1 主要功能与应用场景

Kafka 作为一个分布式流式处理平台,提供了三个关键的功能:

  1. 消息队列:发布和订阅消息流。
  2. 容错的持久化记录消息流:把消息持久化到磁盘,避免了消息丢失的风险·。
  3. 流式处理平台: 在消息发布的时候进行处理,Kafka 提供了一个完整的流式处理类库。

其主要的应用场景:

  1. 消息队列 :实时流数据管道,可靠地在系统或应用程序之间获取数据。
  2. 异步、削峰: 对产生的流量进行削峰和异步处理
  3. 解耦: 解耦消费方和生产方对消息的处理

1.0.2 相比于其他 MQ 的优缺点

Kafka的设计目标是高吞吐量,所以他的一些特性都和这个目标相关,如

  1. Kafka 使用的是顺序 I/O,为保证顺序,Kafka强制点对点的按顺序传递消息,这意味着,一个 consumer 在分区中只有一个位置。

  2. Kafka 不保存每个消息的状态,不提供以随机访问的形式更新消息的状态,而是使用 offset 划分使用和未使用的消息。

  3. Kafka支持点对点的批量消息传递。

  4. Kafka的消息存储使用了 OS pagecache(页缓存,page cache的大小为一页,通常为4K,用于缓存文件的逻辑内容),提高读写文件时的操作效率。

和其他消息队列的对比:

消息队列 / 特性 MsgBroker Kafka RabbitMQ ActiveMQ RocketMq
消息推送模式 push pull 多协议,均支持 多协议,均支持 多协议,均支持
持久化能力 DB 磁盘(文件系统page cache) 磁盘 磁盘 磁盘
事务型消息 支持 不支持 不支持 支持 支持
消息是否有序 无序 有序,采用追加写、offset读 有序 有序 有序
数据可靠性 可靠 replica机制,容错容灾.(依赖ZK中维护的元数据来实现的 ) 保证数据不丢,slave备份 可靠,master/slave 可靠,同步刷盘,同/异步复制
应用场景 金融及支付高可靠性,重点强调事务型 高吞吐量,分布式规模流式数据处理 高可用 高可用 高吞吐,高可靠

1.1 broker \ topic \ partition…关系结构:

Kafka 基础概念_第1张图片
重点部分说明

1. Partition(分区) :

   属于 Topic 的一部分。一个 Topic 可以有多个 Partition(即多副本机制) ,并且同一 Topic 下的 Partition 可以分布在不同的 Broker 上。

kafka 中 ,Producer 在发布消息时可以选择指定要发送的 Partition,或者使用默认的分区策略让 Kafka 自动选择 Partition。

多副本机制是什么?

   Kafka 为 Partition 引入了多副本(Replica)机制。Partition 中的多个副本之间会有一个叫做 leader 的家伙,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。

生产者和消费者只与 leader 副本交互。
follower 保证消息存储的安全性。当 leader 副本发生故障时会从 follower 中选举出一个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。

多分区 以及多副本机制有什么好处呢?

  1. 一个 Topic 下的多个 Partition 可以分布在不同的 Broker 上, 可以提供更好的并发能力(类似负载均衡)。
  2. Partition 的 Replica 机制, 极大地提高了消息存储的安全性, 提高了容灾能力,不过也相应的增加了所需要的存储空间。

2. Consumer Group

   ConsumerGroup 是用来维护一组相同消费者的实例。一个 Consumer Group 可以订阅多个 Topic。

   每个 Partition ,在同一个 Consumer Group 中,一定 会有对应的消费者

一个topic下有多个Partition时,如何保证Consumer消费的顺序性?

Broker 中有如下一些概念:

  • ISR : Leader 副本保持一定同步的 follower 副本, 包括 leader 副本自己,叫 In Sync Replica;
  • AR: 所有副本 (replicas) 统称为 assigned replicas, 即 AR;
  • OSR: follower 同 leader 同步数据有一些延迟的节点;
  • HW : Highwatermark, 俗称高水位,它表示了一个特定的消息偏移量(offset), 在一个 parttion中consumer只能拉取这个 offset 之前的消息(此 offset 跟 consumer offset 不是一个概念) ;
  • LEO: LogEndOffset , 日志末端偏移量, 用来表示当前日志文件中下一条写入消息的offset;

  Kafka 通过ISR的同步机制及优化策略,用 HW & LEO 的方式很好地确保了数据不丢失以及吞吐率。而ISR的管理最终都会反馈到 ZK 上。

1.2 Kafka 消息模型

发布-订阅模型:
Kafka 基础概念_第2张图片
   发布订阅模型(Pub-Sub) 使用主题(Topic) 作为消息通信载体,类似于广播模式;发布者发布一条消息,该消息 通过 Topic 传递给所有的订阅者,在一条消息广播之后才订阅的用户则是收不到该条消息的。
   在发布 - 订阅模型中,如果只有一个订阅者,那它和队列模型就基本是一样(即 Producer和Consumer 一对一消费)。

JMS 和 AMQP 属于消息服务领域权威组织所做的相关的标准。

1.3 Kafka为提高读写效率应用到的技术

1. 顺序写入

   磁盘的读写分为两种方式,顺序IO和随机IO,顺序IO速度和内存基本一致。

   kafka 采用顺序IO记录 Producer 发送的消息到磁盘,Consumer 通过和 ZK 共同维护的 offset 来记录读取到的位置。

2. Memory Mapped Files

   和Java NIO 对文件的操作相同,使用 虚拟内存完成文件到磁盘的映射,需要对文件进行IO操作时,直接操作内存即可,避免了文件在用户空间到内核空间的来回拷贝。

3. 使用 Sendfile 完成“零拷贝”

   零拷贝操作方式下,使用硬件(DMA)的方式完成文件拷贝,不需要拷贝文件到用户空间,所以不消耗 CPU 资源,IO效率提高。关于 操作系统中零拷贝 的更多介绍。

4. 数据压缩与批量发送

   在 Producer 端指定压缩算法(CompressionType)进行压缩,然后发送到 Broker(Broker为了校验数据正确性会解压核对数据),Consumer 读取数据后进行解压。

   数据批量发送,主要通过 buffer.memory、batch.size、linger.ms 参数来控制批量发送数据的大小,充分利用网络传输效率。

1.4 SASL 用户认证

kafka中,不同版本提供的用户认证有如下四种:

  1. SASL/GSSAPI(kerberos):kafka0.9版本推出,即借助kerberos实现用户认证,如果公司恰好有kerberos环境,那么用这个是比较合适的。

  2. SASL/PLAIN:kafka0.10推出,用户名 / 密码明文传输,不能动态添加用户,不建议生产环境使用。

  3. SASL/SCRAM:kafka0.10推出,全名Salted Challenge Response Authentication Mechanism。认证通过sha256等哈希算法,提高了安全性;可以动态添加用户;缺点是某些语言的客户端不支持该方式认证。

  4. SASL/OAUTHBEARER:kafka2.0推出。


二、复杂专题介绍

如何保证消息的可靠性(或如何避免消息丢失)?

  ​ 一条消息的流转,会经过 Producer / Broker / Consumer ,所以消息的丢失,可能出现在这三个位置,我们分情况讨论。具体的实现,可参考:消息可靠性方案的实现

Producer 端消息丢失

Kafka 基础概念_第3张图片
1. Producer 是否等待 TopicLeader 的消息回执(ack:默认为1)

  ​ acks = 1: Leader 写入消息到本地日志,则请求被认为成功。如果此时 Leader 应答请求后挂掉了,消息会丢失

   acks = 0: Producer 执行发送请求后立即返回,不等待 Leader 的确认,消息会丢失

​    acks = -1:分区 Leader 必须等待消息被成功写入到所有的ISR副本(In-Sync Replace)中才认为请求成功。该种情况下配合 Producer 的消息重试机制 来保证消息可靠性

2. Producer 进程意外停止导致的消息丢失

  ​ 为了提升发送效率,减少IO次数,Producer 在发送数据时,可以将多个消息缓存在本地 buffer 中进行合并后发送(主要通过在 KafkaProducer 对象中配置 buffer.memory 、batch.size 、linger.ms 参数来控制)。

  ​ 可以看到存在本地 Buffer 的消息,在 Producer 进程突然结束后,会出现消息丢失的情况。如果有必要,可以适当调小上面提及的参数,使发送频率变高,减少丢失数据。

3. Producer 网络问题导致的消息丢失

  ​ 由于 Producer 的网络问题,在经过 retries 和 retry.backoff.ms 后,依然发送失败,那么将使用其他的方案进行重试发送。

Broker 消息丢失

1. Leader 切换

   Broker 的消息丢失,最容易出现在 Partition Leader 切换时,我们可以通过如下的一些参数来保证 Broker 消息的可靠性

  1. replication.factor 设置 topic 的副本
  2. 服务端设置 min.insync.replicas(ISR)>1,确保切换 Leader 时有同步的 Flower。需要 replication.factor > min.insync.replicas
  3. producer 端设置 acks=all,保证消息写入所有 ISR 列表中
  4. producer 端设置 retries 和 retry.backoff.ms 对 Broker 存储失败的消息进行重发
Consumer 消息丢失

1. Consumer 按时间间隔自动提交 offset

   使用 enable.auto.commit 和 auto.commit.interval.ms 控制异步 offset 提交,可能会出现消息丢失或者重复消费。

2. Consumer 手动提交 offset

   手动提交 offset 并不能 100% 保证消息一定不丢失,(比如,消费某几条消息失败后,导致 offset 没有提交,那么默认情况下,消费者会进行重试,如果重试还是失败,消费者将继续消费下一批消息,如果后续的消费成功提交 offset ,那么消费失败的消息将会丢失),需要配合异常重试、死信队列、死信队列消息处理机制,才能保证 Consumer 100% 不丢失消息。

如何保证消息的唯一性

消息不唯一,可能会出现在 Producer 端多次发送,在 Consumer 端多次消费,下面分情况讨论:

1. Producer 客户端通过 Producer ID(PID)和 Sequence Number 保证消息唯一

   0.11.0 后的版本,引入了 Producer ID(PID)和 Sequence Number 实现 Producer 的幂等,保证一个消息只被投递一次。

2. Consumer 添加持久化的去重判断

   Consumer 消息的消费和业务紧密相关,所以需建立持久化的唯一标识,来避免消息重复消费。

如何保证消息的消费顺序?

Kafka 基础概念_第4张图片

   Kafka 只能为我们保证每个 Partition(分区) 中的消息有序, 同一个 Topic 下的多个 Partition 内的消息在消费时,不保证有序性.

为了保证消息的顺序消费, 有如下几种方案:

  1. 1 个 Topic 只配置一个 Partition
  2. Producer 发送消息的时候指定 key 和 Partition, 保证需要顺序消费的消息在同一个 Partition 中, 此时无论是哪一个 Consumer 来 pull 消息都是有序的.
    • 1 和 2从本质上来讲, 都是利用 Partition 中的有序性来实现顺序消费
  3. 在消息中加入状态(如订单的预下单>支付中>支付完成>撤销), Consumer 消费消息时, 判断状态决定消费还是抛出异常, 异常后等待被重新消费
    • 通过业务来控制有序的消费消息

你可能感兴趣的:(#,Kafka,kafka,java)