当前位置: 首页 > 科技观察

两张图理解kafka应用中broker这个词

时间:2023-03-15 20:31:53 科技观察

Kafka:中间的kafka集群存储消息,是由多台服务器组成的集群。topic:kafka为消息提供的分类方式。Broker用于存储不同主题的消息数据。生产者:在代理中的主题中生产数据。消费者:从代理中的主题获取数据。Kafka中术语设计:1.Broker中间的kafka集群存储消息,是由多个服务器组成的集群。2.主题和消息Kafka将所有消息组织成多个主题存储,每个主题可以拆分成多个分区,每个分区一次由一条消息组成。每条消息都用一个递增的序号来标识,代表它进来的顺序,并按顺序存储在分区中。这样,消息就按照id一个一个的组织起来了。生产者选择一个主题,生产消息,消息会通过分配策略追加到一个分区的末尾。消费者选择一个topic,通过id指定从哪里开始消费消息。消费完成后保留id,下次可以从这个位置继续消费,也可以从其他位置开始消费。上面的id在Kafka中叫做offset。这种组织和处理策略提供了以下好处:消费者可以根据自己的需要灵活指定抵消消费。它保证了消息的不变性,为并发消费提供了线程安全的保证。每个消费者保持自己的偏移量,互不干扰,不存在线程安全问题。消息访问的并行效率。每个主题中的消息被组织成多个分区,分区均匀分布到集群服务器。在生产和消费消息时,它们会被路由到指定的分区,减少竞争,增加程序的并行性。增加消息系统的可扩展性。每个主题中保留的消息可能非常大,通过分区将消息分成多个子消息,分区通过负责任的平衡策略分配给不同的服务器。这样当机器负载满了的时候,可以通过扩容的方式重新均匀分配消息。确保消息的可靠性。消息消费完成后,不会被删除。可以通过重置offset再次消费,保证消息不会丢失。灵活的持久化策略。可以通过指定时间段(如最后一天)保存消息,以节省代理存储空间。备份高可用性。消息以分区为单位分发到多个服务器并以分区为单位进行备份。备份策略为:1个leader和N个follower,leader接受读写请求,followers被动复制leader。leader和follower会分散在集群中,保证分区的高可用。3.每个Partitions的Topic被划分为一个或多个Partition,Partition中的每条消息都标有一个sequentialid,是offset,存储的数据存储时间是可配置的。4.ProducerProducer生产消息需要如下参数:topic:向哪个topic生产消息。分区:向哪个分区生成消息。key:根据key把消息分成不同的partitions。消息:消息。5.Consumer传统的消息系统有两种模式:Queue、发布和订阅。Kafka通过消费者组统一处理两种模式:每个消费者会自己标记消费组的名字,然后系统会根据名字对消费者组进行分组,复制分发消息给所有的组,只有一个每个组中的消费者都可以消费这条消息。如下图所示:于是推导出两种极端情况:当所有消费者的消费组相同时,系统变成队列模式;当每个consumer的consumer-group不同时,系统就变成了publish-subscribe注:1.ConsumerGroups提供了topic和partitions的隔离,如上图,当ConsumerGroupA中的consumer-C2挂了,consumer-C1会收到P1和P2,即一个消费组中的其他消费者挂掉后可以重新平衡。如下图所示:2.当多个消费者并发消费消息时,很容易造成消息乱序。通过限制消费者的同步,可以保证消息的顺序,但是这样会大大降低程序的并发度。kafka通过分区的概念,保证了消息在分区中的顺序,缓解了上述问题。分区中的消息会被复制分发到所有组中,每个组中只有一个消费者可以消费这条消息。这种语义保证一个组同步地而不是并发地消费来自某个分区的消息。如果一个topic只有一个partition,那么这个topic的并发消费是有序的,否则只有一个partition是有序的。在一般的消息系统中,消费者有两种消费模式:推送:优势在于信息的实时性高。缺点是没有考虑消费者的消费能力和饱和度,容易造成生产者压倒消费者。pull:优点是可以控制消费速度和数量,保证消费不会饱和。缺点是当没有数据时,会出现空轮询,消耗cpu。Kafka使用pull,使用可配置的参数来保证当有数据并且数据量达到一定量时,consumer端才会进行pull操作,否则一直处于block状态。Kakfa使用整型值消费者位置记录单个分区的消费状态,单个分区的一条消息只能被消费组中的一个消费者消费,维护简单,开销小。消费完成后,broker收到确认,position指向下一次消费的offset。由于消息不会被删除,在消费完成并更新position后,消费者仍然可以重新设置offset再次消费历史消息。消息发送语义从生产者的角度来看,消息最多发送一次:生产者异步发送消息,或者同步发送消息但重试次数为0。消息至少发送一次:生产者发送同步消息,失败或超时重试。仅发送一次消息:后续版本支持。从消费者的角度来看,一条消息最多只能被消费一次:消费者先读取消息,然后确认位置,最后处理消息。消息至少被消费一次:消费者先读取消息,然后处理消息,最后确认位置。消息被消费并且只被消费一次。注意:如果消息处理后的输出端(比如db)可以保证消息更新的幂等性,那么多次消费也可以保证exactlyonce语义。如果输出终端能够支持两阶段提交协议,则可以保证确认位置和处理输出消息同时成功或失败。更新后的位置保存在消息处理的输出端,保证了确认位置和处理输出消息的原子性(简单通用)。可用性在Kafka中,正常情况下,所有节点都处于同步状态。当一个节点处于异步状态时,就意味着整个系统出现了问题,需要进行容错。同步的意思是:节点可以和zookeeper通信。如果节点是follower,consumer的位置和leader的位置不能相差太大(相差可配置)。一个分区中同步的节点组成一个集合,就是该分区的ISR。Kafka通过两种方式实现容错:数据备份:以分区为单位进行备份,副本数量可以设置。当副本数为N时,代表1个leader和N-1个follower。Followers可以看作是leader的消费者,它拉取leader的消息附加到自己的系统failover中:1.当leader不同步时,系统从followers中选举出一个新的leader2。当follower出现不同步时,leader将follower从ISR中移除,待follower恢复并完成数据同步后重新进入ISR。另外,Kafka有一个保证:当生产者生产一条消息时,只有当这条消息得到所有ISR的确认时,才意味着这条消息提交成功。只有成功提交的消息才能被消费者消费。因此,当有N个副本,都在ISR中,且N-1个副本全部异常时,系统仍然可以提供服务。假设N个副本全部宕机,节点恢复后将面临同步数据的过程。在此期间,ISR中没有节点,会导致分区服务不可用。Kafka采用降级措施来处理:选举第一个恢复的节点作为leader提供服务,并以其数据为基准。这种措施称为肮脏的领导人选举。由于leader主要提供服务,kafkabroker将多个partition的leader分布在不同的服务器上,以分担风险。每个分区都有一个领导者。如果每个分区都运行leader选举过程,会导致很多leader选举过程。Kakfa采用了一种轻量级的方式:选择其中一个broker集群作为controller,这个controller监控被挂起的broker,并为上述分区批量选主。Consistency上面的方案保证了数据的高可用,有时高可用是牺牲了一致性来体现的。如果要实现强一致性,可以采取以下措施:禁用脏领导选举。当ISR没有节点时,不提供服务比不完全同步的节点更好。设置最少的ISR数min_isr,保证消息在提交前至少要经过min_isr个节点的确认。持久化基于Kafka严重依赖磁盘而不是内存来存储消息这一事实。硬盘便宜,内存贵。顺序读+预读操作可以提高缓存效率。读取数据,写入缓存并返回(在操作系统后台刷新),提高用户进程的响应速度。java对象的实际大小比理想大小要大,这使得在内存中存储消息的成本非常高。当堆内存使用量持续增加时,gc抖动比较大。设计思路基于文件的顺序读写,代码编写简单。在持久化数据结构的选择上,Kafka使用了queue而不是Btreekafka,它只是简单的根据offset进行读取和追加,所以基于queue的操作时间复杂度为O(1),而基于Btree的操作时间复杂度为O(logN)。当读写大量文件时,基于队列的read和append只需要一次磁盘寻址,而Btree会涉及多次。磁盘寻址过程大大降低了读写性能