Kafka设计原理,为什么Kafka性能高?如何保证Kafka不丢消息?

分布式消息中间件

作用:

1. 解耦(同步调用是一种强依赖,而异步调用是一种弱依赖);

2. 削峰填谷;

3. 降低响应时间;

4. 提升吞吐量(Kafka 的吞吐量是MySQL 吞吐量的30-40倍,并且Kafka的扩展性远高于MySQL);

Kafka 的设计原理

Kafka 是一个分布式消息中间件,但是它并不符合JMS 规范,即使消息已经被消费,也不会被马上删除,当消息保留一定时间后,会被批量删除。

在Kafka 中,消息被持久化到磁盘上,因此Kafka 堆积消息的能力非常强大。

Kafka 依赖于 Zookeeper 管理元数据。

Kafka 架构图

Kafka设计原理,为什么Kafka性能高?如何保证Kafka不丢消息?

Broker

Kafka的服务端,负责接收数据,并持久化数据,Broker 可以有多个,每个Broker 可以包含多个 Topic,Broker 并不保存 Offset(消费者消费的位置)数据,由 Consumer 自己负责保存,默认保存在 ZooKeeper 中。

Producer 生产者

生产数据发送到Broker 存储数据。Producer 直连 Broker,不经过任何代理,Producer 将会和 Topic 下所有 Partition Leader 保持 Socket 连接。通常 Producer 是一个包含 Kafka客户端的业务服务。

Consumer 消费者

业务服务从 Broker 订阅Topic,并从 Topic 中接收数据。

每个消费者都属于某个消费者组,一个组里的消费者订阅的是同一个Topic,同一个组的消费者分别订阅同一个 Topic下的不同 Partition 的数据。

需要注意的是,每个 Partition 只能被一个消费者订阅,一个消费者可以订阅多个 Partition,用这种方式避免一定的重复消费。

当一个消费者挂掉之后,会重新进行负载均衡。

Topic 主题

相当于数据库找那个的表名,生产者和消费者之间通过 Topic 建立对应关系。

Topic 更像一个逻辑概念,每个 Topic 下包含了多个 Partition,所有元数据都存储在 ZooKeeper 中。

Partition 分区

Kafka 为了扩展性,提升性能,可以将一个 Topic 拆分为多个分区,每个分区可以独立放到一个 Broker 中。

ZooKeeper

Kafka将元数据信息保存在Zookeeper中,但是发送给Topic本身的数据是不会发到ZooKeeper上。

Kafka 使用Zookeeper来实现动态的集群扩展,不需要更改客户端(producer和consumer)的配置。Broker会在Zookeeper注册并保持相关的元数据(topic,partition信息等)更新。

而客户端会在Zookeeper上注册相关的watcher。一旦zookeeper发生变化,客户端能及时感知并作出相应调整。这样就保证了添加或去除Broker时,各Broker间仍能自动实现负载均衡。

这里的客户端指的是Kafka的消息生产端(Producer)和消息消费端(Consumer)。Producer端使用Zookeeper用来"发现"broker列表,以及和Topic下每个partition的Leader建立socket连接并发送消息。也就是说每个Topic的partition是由Leader角色的Broker端使用Zookeeper来注册Broker信息,以及监测partition leader存活性。Consumer端使用Zookeeper用来注册Consumer信息,其中包括Consumer 消费的partition列表等,同时也用来发现broker列表,并和partition leader建立socket连接,并获取消息。

ZooKeeper 在Kafka 集群中承担的作用

  • Zookeeper管理着Kafka集群中的若干个Broker,保存着一份完整的Broker列表。
  • 维护Topic信息,比如Partitions、Replication Factor、ISR(In-sync Replica)等。
  • Zookeeper帮助选举Partition的Leader。
  • 当有任何变动时,由Zookeeper给Kafka发送通知,比如添加一个新的Topic、Broker挂掉了、删除Topic等等。
  • Zookeeper集群中也有Leader和Follower的概念。Leader负责写数据,Follower负责读数据.
  • 存储Kafka集群ID。
  • 存储访问控制列表(ACL,Access Control List)。控制Topic、Consumer Group、User等访问权限。

Kafka设计原理,为什么Kafka性能高?如何保证Kafka不丢消息?

为什么 Kafka 性能高?

  • 顺序写磁盘,媲美内存随机访问的性能。

顺序写磁盘的性能是随机写入的性能的6000倍的提升,磁盘不再是瓶颈点。

  • 零拷贝技术,减少上下文切换和拷贝次数。

如何保证Kafka 不丢消息?

1. ACK 机制

通过 ACK 机制保证消息送达。Kafka 采用的是至少一次(At least once),消息不会丢,但是可能会重复传输。

2. 复制机制

Kafka 保证可靠性依赖的是复制机制,因为单机容易出现故障。Kafka 以Topic 为单位进行设置复制因子,以 Partition 为单位进行复制,允许一份数据复制到集群中的多个节点上。通过复制,Kafka 在Broker 集群中的部分节点挂掉的情况下,仍然可以继续发送和接收消息。

Kafka设计原理,为什么Kafka性能高?如何保证Kafka不丢消息?

3. 消息删除机制

Broker 端删除消息有一个配置策略,默认是7天,如果7天消息还没有消费,则有可能被删除,也就是丢消息了。

4. 发送消息

为了得到更好的性能,Kafka 支持在生产者一侧进行本地buffer,也就是累积到一定的条数才发送,如果这里设置不当是会丢消息的。

生产者端设置 producer.type=async, sync,默认是 sync。

当设置为 async,会大幅提升性能,因为生产者会在本地缓冲消息,并适时批量发送。

如果对可靠性要求高,那么这里可以设置为 sync 同步发送。

5. 消费消息

如果更注重可靠性,则需要显示提交 Offset,也就是当所有业务都处理完成的时候,再提交 Offset。这样会导致重复消费,需要提供幂等性接口。

相关推荐