前言Kafka最初由LinkedIn开发,是一个高吞吐量的分布式发布订阅消息系统,现在已经成为大多数公司使用的技术。我们公司也不例外。那么你对kafka了解多少呢?那么这篇文章就带大家了解一下kafka中的一些关键点。为什么我们需要卡夫卡?在订单发生时通知其他服务在我们深入研究之前,值得重新审视一下为什么首先要发明Kafka。想象一下为一家电子商务公司维护一组微服务。下订单时,订单服务会通知很多服务,如下:钱包服务从用户账户中扣除金额仓库服务扣除物品的库存数量物流服务发货当订单服务需要通知更多服务时,复杂度会得到进一步提高。订单服务器需要做以下事情:跟踪谁被通知以确保所有其他服务确实被接收和处理与其他服务建立直接连接并处理不同的响应发现没有,这很难扩展,如果更多系统是connected,order系统开发每天996。因此,Kafka很好地解决了此类问题。消息队列和发布订阅订单服务器只是将消息发布到Pub-Sub/MessageQueue。消息队列和发布订阅系统是解决上述问题的关键。也就是说,不是让订单服务维护直接与各个系统打交道,而是将事件发布或推送到一个中间队列,由对队列感兴趣的服务器(通常称为消费者)订阅队列并相应地消费事件。那么消息队列和发布订阅系统有什么区别呢?MessageQueue消息队列是一种类似于队列的结构,其中消息只发布和使用一次。这对于事件只能由一个消费者处理的非幂等过程来说很方便。RabbitMQ最初设计为消息队列。发布-订阅系统另一方面,发布-订阅系统允许多个消费者多次消费一条消息。订单事件被多个系统订阅和消费,更适合发布-订阅系统模式。Kafka被设计为既是消息队列又是发布-订阅系统。Kafka组件为了充分理解Kafka的工作原理,让我们剖析Kafka的各个组件。KafkaBroker和ClusterKafkaBroker和ClusterKafka无非是一个管理数据发布和消费的服务。KafkaBroker是一种Kafka服务。一组维护同一组主题的Brokers称为Kafka集群。发布者Publisher发布者发布到KafkaBroker将数据发布到KafkaBroker的服务称为发布者。我们前面提到的Order服务就是Publisher的一个例子。Consumers消费者从Kafkabroker消费另一方面,消费者是订阅和消费来自Kafka主题的数据的服务。在我们前面的示例中,钱包服务器、仓库服务器和物流服务器充当订单主题的消费者。Topic不同的TopicKafkaBrokers在TopicKafkaBroker中维护着不同类型的事件,例如:OrderCreatedEventsOrderCancelledEventsOutofStockEvents这些事件中的每一个都是海量的数据流。主题只是事件或数据流。发布到Kafka时,发布者指定消息应该发布到的主题。主题是一个只能追加的日志。向主题追加消息类似于向队列追加数据,需要O(1)常量时间,因此非常快。分区分区主题被分割成分区主题是存储在KafkaBroker上的附加日志。随着消息数量的增加,Broker存储的关于特定主题的数据量是有限的,那怎么办呢?一个主题可以分成多个分区,而不是将所有数据一直附加到同一个主体日志,每个分区存储特定主题的一部分数据,类似于数据库分片。主题基于分区进行分片。同一主题的分区可以存储在相同或不同的KafkaBrokers上。这使得Kafka具有高度可扩展性。发布者在发布前指定消息的主题和分区。因此,发布者有责任确保分区逻辑不会导致热分区。分区中的偏移量是消息在分区中的唯一索引。当Kafka将数据推送给消费者时,它会增加并跟踪当前的偏移量。有两种偏移量值得强调:当前偏移量:存储在Consumer客户端中,表示Consumer要接收的下一条消息的序号。Submittedoffset:保存在Broker上,表示Consumer已经确认消费的消息序号。消费组前面说了,Kafka既是消息队列又是发布订阅系统。这是通过消费者群体精心设计的。消费者可以消费多个分区,但每个分区只能被同一组中的一个消费者消费。消费者组由一组消费相同主题的消费者组成。一个消费者一次可以消费多个分区。但是,每个分区只能由同一组中的一个且只有一个消费者使用。一个分区可以被来自不同消费者组的多个消费者消费。消费者组相互独立,不同的组可以同时使用同一个topic,使用不同的offset。队列是通过将所有消费者放在同一个组中来实现的,同一分区中的消息不会被来自相似组的不同消费者同时消费。在分区级别实现队列。因此,发布者要想保证数据流的有序处理,就必须确保数据始终被推送到同一个分区。另一方面,发布-订阅系统是用多个消费者组实现的。消费者群体彼此之间一无所知,并使用单独的偏移量消费数据。在前面的例子中,Wallet服务器和Logistic服务器属于不同的消费组,分别消费数据。重新平衡和分区分配Kafka在新消费者加入时重新平衡。如果一组中只有一个消费者,则该消费者将负责消费所有可用分区。当有新的消费者加入该组时,例如添加新的服务器实例,Kafka将执行重新平衡并将一些分区分配给新的消费者。这确保了每个消费者共享相同数量的工作,使Kafka具有可扩展性。Kafka使用自己的rebalancing策略进行分区重分配,值得单独写一篇文章。副本在分区级别创建,可以存储在相同/不同的代理中。单点故障是每个分布式系统的噩梦,Kafka也不例外。如果Broker发生故障,则存储在Broker上的分区可能不可用。因此,副本是在分区级别创建的。为每个分区创建副本并存储在不同的Kafka代理上。为每个分区选出一个领导者来服务发布者和消费者。副本不断地从领导者那里同步数据。当leader宕机时,Zookeeper会加入进来,帮助进行leader的选举。Zookeeper正如您所想,我们的难题中缺少一些部分。我们如何知道每个分区的领导者?如何知道每个主题的分区数?我们如何知道每个消费者组的最新偏移量?我们如何知道每个消费者组中有多少消费者?这就是Zookeeper发挥作用的地方。它是Kafka中用于存储元数据和协调分布式系统的分布式协调服务系统。主要涉及以下内容:LeaderElection-确保每个分区都有一个leaderclustermembership-跟踪集群中所有功能性broker主题配置-跟踪所有可用的主题、分区及其副本AccessControlList-跟踪消费者数量在每个组中及其访问配额-跟踪每个客户端可以读取和写入多少数据长轮询Kafka如何向消费者推送消息?RabbitMQ使用推送模型。代理与消费者保持持久的TCP连接,并在数据可用时将数据推送给他们。然而,推送模式可能会让消费者不知所措。如果代理推送数据的速度快于消费者处理数据的速度,消费者可能会落后。RabbitMQ确实有解决办法,这里就不展开讨论了。Longpolling等待方式Kafka采用的是pull模型,也就是longpolling。消费者定期从代理中提取数据。因此,消费者只有在准备好时才能拉取数据。但是,如果分区上没有数据,来自消费者的定期轮询可能会浪费资源。Kafka通过使用“长轮询”等待模式解决了这个问题。简而言之,如果分区上没有数据,Kafka不会返回空响??应。相反,代理保持连接打开并等待数据进入,然后再将其返回给消费者。这样可以避免消费者频繁轮询,防止分区上没有数据时的资源浪费。小结本文总结了Kafka组件的基础知识,希望能让大家对Kafka有个宏观的认识,感兴趣的再深入分析底层实现机制。
