KafKa消息中间件

1. 为什么要有消息中间件

        在业务系统中,完成一个业务流程通常会有很多步骤,甚至跨越多个系统,这些步骤之间有相互的信息交互和顺序依赖。为了降低系统之间的强耦合关系,会选用一个中间件系统通信,这也是消息中间件系统的主要功能之一。

  • 解耦:通过消息中间件解除相关系统之间的强耦合关系;
  • 异步:将很长的业务流程分拆成几个部分,请求异步化
  • 削峰:对于秒杀、抢购等系统,瞬时流量非常大,通过消息削峰;
  • 高性能:一个业务请求如果采用同步等待,会占用系统一个线程资源,但是大部分的业务请求可以快速相应返回,请求异步化,有助于提高系统的性能。

2. 消息队列通信模式

  • 点对点模式:点对点模式通常是基于拉取或者轮询的消息传送模型,特点是发送到队列的消息被一个且只有一个消费者进行处理;
  • 发布订阅模式:生产者将消息放入消息队列后,队列会将消息推送给订阅过该类消息的消费者;

3. kafka一些常见知识点总结

1、什么是kafka

Apache Kafka是由Apache开发的一种发布订阅消息系统,它是一个分布式的、分区的和重复的日志服务。kafka是由scala语言编写。

2、kafka有哪些组成

producer: 消息的生产者

broker:一个单独的kafka server就是一个broker ,负责消息的读取和存储,一个broker可以管理多个partition。

Topic:消息主题,可以理解为消息的分类,kafka的数据就保存在topic。在每个broker上都可以创建多个topic。

Partition:Topic的分区,每个topic可以有多个分区,分区的作用是做负载,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,partition的表现形式就是一个一个的文件夹。

Replication:每一个分区都有多个副本,当主分区(Leader)故障时,会选择一个副本作为Leader。kafka中默认副本的最大数量是10个,且副本的数量不能大于Broker的数量,follower和leader绝对是在不同的机器。

Message:每一条发送的消息主体。

Consumer:消费者。

Consumer Group:将多个消费者组成一个消费者组,在kafka的设计中同一个分区的数据只能被消费者组中的某一个消费者消费。同一个消费者组的消费者可以消费同一个topic的不同分区的数据,这也是为了提高kafka的吞吐量!

Zookeeper:kafka集群依赖zookeeper来保存集群的的元信息,保证分布式一致性

3、kafka消息是怎样产生的,消息是否有大小限制,消息是否是有序的

        kafka的消息都是以(key,value)形式存在,生产者决定数据写到那个partition,每个消息的大小不超过1M。

  • producer从集群获取分区的leader;
  • producer主动将消息推送到leader;
  • leader将消息写入本地文件;
  • follower主动从leader拉取消息,写入本地文件后返回ack信息;
  • leader确认follower的ack信息后,然后返回消息的ack信息给producer。

        对于消息的ack机制,主要有三种:不等待broker的回应,等待leader的回应以及等待leader和所有follower的回应。每个消息在被添加到分区时,都会被分配一个offset,它是此消息在分区中的唯一编号,kafka通过offset保证消息在分区内的顺序,offset顺序不跨分区,即kafka只保证在同一个分区内的消息是有序的,在不同的分区中,消息可能是无序的。

图片来自:kafka - 搜索结果 - 知乎 

4、kafka的消息是如何存储的

        kafka消息以固定格式存储在磁盘上.log文件中:消息由一个固定长度的头部和可变长度的字节数组组成。头部包含了一个版本号和CRC32校验码。消息主要包含消息体、消息大小、offset、压缩类型……等等。offset是一个8byte的有序id号,可以唯一确定消息在parition内的位置;消息大小占用4byte;

        kafka在broker上一个topic的partition是一个文件夹,每个partition文件夹下有多个segment(xxx.index,xxx.log,xxx.timeindex),segment文件的大小可以通过配置设置,默认为1G。大小大于1g时,会滚动一个新的segment并且以上一个segment最后一条消息的偏移量命名。kafka就是利用分段+索引的方式来解决查找效率的问题。

5、为了避免磁盘占满,kafka会周期性的清除过期消息,有什么策略,什么是日志压缩

        kafka会根据策略定期清除过期消息,策略包括:根据消息的保存时间和根据topic存储数据的大小。

        日志压缩是:在很多场景下,消息的key与value对应关系是不断变化的,消费者只关心key对应的最新value,此时,可以开启kafka的日志压缩功能,kafka会在后台启动一个线程,定期将相同key的消息进行合并,只保留最新的value值。

6、kafka如何快速查找到消息

  • 根据消息的offset,找到message所在的segment文件(利用二分法查找)
  • 找到segment中的.index文件,由于该文件采用的是稀疏索引的方式存储着相对offset及对应message物理偏移量的关系,所以直接找相对offset的索引可能找不到,同样利用二分法查找相对offset小于或者等于指定的相对offset的索引条目中最大的那个相对offset;
  • 找到.index文件中的物理位置,然后打开.log文件从物理位置顺序扫描,直到找到Message。

7、kafka消息怎样消费,是push还是pull,消费组的消息能不能重复消费,怎样扩展消费组

        消费者会记录消息消费的物理偏移量位置(offset),下一次消费的时候,会接着上一次的位置继续消费。consumer采用pull模式拉取消息,好处是可以根据consumer的消费能力决定消息消费速度,但缺点是如果broker没有消息,会不断轮询,直到新的消息产生,所以kafka可以通过设置让consumer阻塞。kafka支持多个consumer组成一个consumer group,在一个group中,每个partition只会被分配到一个consumer,如果组中members太多,可能会有member空闲。

8、kafka创建topic时,怎么将分区放到不同的broker,新建的分区会在哪个目录下创建

        创建topic时,第一个分区的第一个副本,会从brokerlist中随机选取一个broker;其它分区的第一个副本,会在紧随第一个分区的broker后。剩余的副本则相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的。

        分区文件夹的创建,会根据启动kafka时配置的log.dirs参数决定。如果log.dirs值配置了一个参数目录,则分配到broker上的partition也会在这个目录下创建。如果log.dirs配置了多个目录,Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic名+分区ID。

9、什么是ISR,由谁维护,怎么维护

        ISR(In-Sync Replica)中的副本都是与Leader进行同步的副本,所以不在该列表的follower会被认为与Leader是不同步的。可以明确的是:Leader副本总是存在于ISR中,而follower副本是否在ISR中,取决于该follower副本是否与Leader副本保持了“同步”。每个分区都有一个同步副本列表,该列表由Leader分区和Controller进行更新。选择一个同步副本列表中的分区作为leader 分区的过程称为clean leader election,在非同步副本中选一个分区作为leader的过程称之为unclean leader election。

         kafka写请求先交给leader处理,follower副本会从leader那里拉取写入的消息。这个过程可能会有一定的延迟,导致followers的副本消息落后于leader,如果超过阈值后,follower会从ISR中移除到OSR中。通常情况下,ISR应该包含所有的副本,当ISR中所有Replica都向Leader发送ACK时,leader才commit。不幸的是,unclean leader election可能会造成数据的不一致,这受到两个参数的影响:

  • replica.lag.time.max.ms:同步副本滞后与leader副本的时间
  • zookeeper.session.timeout.ms:与zookeeper会话超时时间

10、kafka的controller broker

        Controller是kafka的核心组件,主要作用是在zookeeper帮助下管理集群,集群中任意一台 Broker 都能充当控制器的角色,但在运行过程中只能有一个 Broker 成为控制器。Broker 在启动时,会尝试去 ZooKeeper 中创建 /controller 节点,第一个成功创建 /controller 节点的 Broker 会被指定为控制器。Controller Broker的主要职责包括以下几个方面:

  • 创建、删除主题,增加分区并分配leader分区
  • 集群Broker管理(新增 Broker、Broker 主动关闭、Broker 故障)
  • preferred leader选举
  • 分区重分配

每个 Broker 启动后,会在zookeeper的 /Brokers/ids 下创建一个临时 znode。当 Broker 宕机或主动关闭后,该 Broker 与 ZooKeeper 的会话结束,这个 znode 会被自动删除。ZooKeeper Watch 机制将这一变更推送给控制器,控制器就能知道有 Broker 关闭或宕机了,从而进行后续的协调操作。

        Kafka认为leader分区副本最初的分配(每个节点都处于活跃状态)是均衡的(均匀分配在不同机器),这些被最初选中的分区副本就是所谓的首选领导者(preferred leaders)。默认情况下auto.leader.rebalance.enabled为true,表示允许 Kafka 定期地对一些 Topic 分区进行
Leader 重选举。当Controller注意到Broker已加入集群时,它将使用Broker ID来检查该Broker上是否存在分区,如果存在,则Controller通知新加入的Broker和现有的Broker,新的Broker上面的follower分区再次开始复制现有leader分区的消息。为了保证负载均衡,Controller会将新加入的Broker上的follower分区选举为leader分区。

11、kafka的leader重选举过程

        kafka副本以topic的分区为单位,正常情况下每个分区都有一个单独的leader,0个或多个follower,副本的总数包括leader。所有的读取和写入到该分区的leader,leader均匀分布在broker。kafka通过将Leader副本均匀地分布在集群的不同Broker上,保障集群的负载均衡。

        对于kafka的节点活着有2个条件:一个节点必须能维持与zookeeper的会话;如果它是一个slave,它必须复制leader并且不能落后"太多"。如果一个follower死掉,卡住,或落后,leader将从同步副本列表中移除它。当leader故障后,需要从follower中选出新的leader,kafka优先从ISR中的副本选取leader。选择方式是通过controller选举leader,controller会将Leader的改变直接通过RPC的方式(比ZooKeeper Queue的方式更高效)通知需为此作为响应的Broker。具体选举过程如下:

  • 从Zookeeper中读取当前分区的所有ISR(in-sync replicas)集合
  • 调用配置的分区选择算法选择分区的leader。
    • NoOpLeaderSelector: 不做任何变化
    • ControlledShutdownLeaderSelector:找出已经分配的副本,过滤出仍存活的副本集合(liveAssignedReplicas),在该列表中选取第一个broker作为该分区的leader。
    • PreferredReplicaPartitionLeaderSelector:即将AR里的第一个取出,作为优化后的leader。
    • ReassignedPartitionLeaderSelector:在某个topic重新分配分区的时候,触发新的主副本选举,将存活的ISR中的第一个副本选举成为eader。
    • OfflinePartitionLeaderSelector:如果至少有一个broker在ISR列表中,并且存活,则将其选为leader;如果ISR列表为空,且unclean.leader.election.enable=false,则报错NoReplicaOnlineException;如果unclean.leader.election.enable=true,即在AR列表中选出Leader,但是这样会引起数据不一致;若AR列表也为空,则报错NoReplicaOnlineException

        在Broker发生故障时,某些Broker上的分区副本会被选举为leader,会造成一个Broker上存在多个leader分区副本的情况,由于客户端只与leader分区副本交互,所以这会给Broker增加额外的负担,并损害集群的性能和运行状况。

11、data replication 如何处理Replica恢复,如何处理replica的全部宕机

如果leader挂掉了,会从replica中选取一个做为新的leader,并且从ISR中移除。如果所有的副本都宕机后,有两种策略:

  • 等待ISR中的任意一个replica恢复,并选举为leader;如果ISR中一个也不能恢复,该Partition永久不可用;
  • 选取第一个回复的replica作为leader,不论是不是在ISR中。

12、消费者rebalance

消费者实现rebalance是通过coordinator实现的。

  • 什么是coordinator: 每个consumer group都会选择一个broker作为自己的coordinator,负责监控这个消费组里的各个消费者的心跳,以及判断是否宕机,然后开启rebalance;
  • 如何选择coordinator机器:首先对groupId进行hash(数字),接着对__consumer_offsets的分区数量取模,默认是50,_consumer_offsets的分区数可以通过offsets.topic.num.partitions来设置,找到分区以后,这个分区所在的broker机器就是coordinator机器。比如说:groupId,“myconsumer_group” -> hash值(数字)-> 对50取模 -> 8 __consumer_offsets 这个主题的8号分区在哪台broker上面,那一台就是coordinator 就知道这个consumer group下的所有的消费者提交offset的时候是往哪个分区去提交offset;
  • coordinator Rebalance过程如下:

    • 1)每个consumer都发送JoinGroup请求到Coordinator; 
    • 2)然后Coordinator从一个consumer group中选择一个consumer作为leader; 
    • 3)把consumer group情况发送给这个leader;
    • 4)接着这个leader会负责制定消费方案,通过SyncGroup发给Coordinator ;
    • 5)接着Coordinator就把消费方案下发给各个consumer,他们会从指定的分区的 leader broker开始进行socket连接以及消费消息;
  • 有三种rebalance的策略:range、round-robin、sticky

13、kafka如何保证消息不丢失,不重复消费

消息丢失从生产端和消费端分析。生产端:

  • 1) 使用同步模式时,有3种状态保证消息被安全生产,在配置为1(只保证写入leader成功的话),如果刚好leader partition挂了,数据就会丢失;
  • 2)使用异步模式的时候,当缓存区满了,如果配置为0(还没收到确认的情况下,缓冲池一满,就清空缓冲池里的消息),数据就会被立马丢弃掉;

消费端:consumer从集群中拉取到到消息后,消息还没有消费成功,自动提交了offset;

对于重复消费,可以对每一个消费的消息在外部加一个去重处理,或者幂等处理。

14、kafka脑裂

        当controller broker挂掉后,Kafka集群必须找到可以替代的controller。但是当集群选举出新的controller后,原来的controller有恢复过来,这个时候就会有两个controller,这种情况称之为脑裂。比如,原来的controller由于GC而被认为已经挂掉。Kafka是通过使用epoch number(纪元编号)来解决脑裂问题的。epoch number是单调递增的数字,第次选出Controller后,epoch number加1。其他Broker 如果收到由controller发出的包含较旧(较小)epoch number的消息,就会忽略它们,即Broker根据最大的epoch number来区分当前最新的controller。

15、kafka linux sendfile技术 — 零拷贝

        kafka服务去os cache缓存读取数据,缓存没有就去磁盘读取数据;os cache复制数据到kafka应用程序中,并不会再次复制到用户空间,而是将数据(复制)发送到socket cache中;socket cache通过网卡传输给消费者。

16、kafka选举过程汇总

控制器的选举:broker启动的时候,通过向zookeeper注册临时节点,第一个注册成功的broker成为controller;

分区leader选举:通过controller从ISR/副本中选取,一般默认选取存活列表中的第一个;

GroupCoordinator选举:负责执行消费者的分区分配和再均衡操作,通过消费组的groupId的哈希值计算__consumer_offsets中的分区编号,找到分区后,再寻找分区leader副本所在的broker节点,该节点就是对应的GroupCoordinator。

消费组leader选举:当消费组内还没有leader,第一个加入消费组的消费者即为消费组的leader,如果当前leader退出消费组,则会挑选以HashMap结构保存的消费者节点数据中,第一个键值对来作为leader。

17、kafka的事务Transaction

        Kafka 在 0.11版本引入事务支持,生产和消费可以跨分区和会话,要么全部成功,要么全部失败。为了管理 Transaction,Kafka 引入了一个新的组件 Transaction Coordinator。Producer 通过和 Transaction Coordinator 交互获得 Transaction ID 对应的任务状态。Transaction Coordinator 还负责将事务所有写入 Kafka 的一个内部 Topic,这样即使服务重启,进行中的事务状态可以得到恢复。

        consumer事务性较弱,主要是 Consumer 可以通过 offset 访问任意信息,而且不同的Segment File 生命周期不同,同一事务的消息可能会出现重启后被删除的情况。      

参考链接:https://zhuanlan.zhihu.com/p/446774729
参考链接:https://www.orchome.com/22

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值