一文从零了解Kafka的原理和执行流程

一、简介

根据官网的介绍,Apache Kafka是分布式发布-订阅消息系统,在 kafka官网上对 kafka 的定义:一个分布式发布-订阅消息传递系统。 它最初由LinkedIn公司开发,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。Kafka是一种快速、可扩展的、设计内在就是分布式的,分区的和可复制的提交日志服务。它主要有3种功能:

  1:It lets you publish and subscribe to streams of records.发布和订阅消息流,这个功能类似于消息队列,这也是kafka归类为消息队列框架的原因

  2:It lets you store streams of records in a fault-tolerant way.以容错的方式记录消息流,kafka以文件的方式来存储消息流

  3:It lets you process streams of records as they occur.可以再消息发布的时候进行处理

二、Kafka基本架构

1、话题(Topic):是特定类型的消息流。消息是字节的有效负载(Payload),话题是消息的分类名或种子(Feed)名;

2、生产者(Producer):是能够发布消息到话题的任何对象;

3、服务代理(Broker):已发布的消息保存在一组服务器中,它们被称为代理(Broker)或Kafka集群;

4、消费者(Consumer):可以订阅一个或多个话题,并从Broker拉数据,从而消费这些已发布的消息;

三、基本原理

我们将消息的发布(publish)称作 producer,将消息的订阅(subscribe)表述为 consumer,将中间的存储阵列称作 broker(代理),这样就可以大致描绘出这样一个场面:

这里写图片描述

生产者将数据生产出来,交给 broker 进行存储,消费者需要消费数据了,就从broker中去拿出数据来,然后完成一系列对数据的处理操作。

乍一看返也太简单了,不是说了它是分布式吗,难道把 producer、 broker 和 consumer 放在三台不同的机器上就算是分布式了吗。看 kafka 官方给出的图:
这里写图片描述

多个 broker 协同合作,producer 和 consumer 部署在各个业务逻辑中被频繁的调用,三者通过 zookeeper管理协调请求和转发。这样一个高性能的分布式消息发布订阅系统就完成了。

图上有个细节需要注意,producer 到 broker 的过程是 push,也就是有数据就推送到 broker,而 consumer 到 broker 的过程是 pull,是通过 consumer 主动去拉数据的,而不是 broker 把数据主懂发送到 consumer 端的。

四、Zookeeper在kafka的作用

上述,提到了Zookeeper,那么Zookeeper在kafka的作用是什么?

(1)无论是kafka集群,还是producer和consumer都依赖于zookeeper来保证系统可用性集群保存一些meta信息。

(2)Kafka使用zookeeper作为其分布式协调框架,很好的将消息生产、消息存储、消息消费的过程结合在一起。

(3)同时借助zookeeper,kafka能够生产者、消费者和broker在内的所以组件在无状态的情况下,建立起生产者和消费者的订阅关系,并实现生产者与消费者的负载均衡。

1、Broker

      中间的kafka cluster,存储消息,是由多个server组成的集群。

2、topic与消息

kafka将所有消息组织成多个topic的形式存储,而每个topic又可以拆分成多个partition,每个partition又由一个一个消息组成。每个消息都被标识了一个递增序列号代表其进来的先后顺序,并按顺序存储在partition中。

这样,消息就以一个个id的方式,组织起来。

 producer选择一个topic,生产消息,消息会通过分配策略append到某个partition末尾。
 consumer选择一个topic,通过id指定从哪个位置开始消费消息。消费完成之后保留id,下次可以从这个位置开始继续消费,也可以从其他任意位置开始消费。
上面的id在kafka中称为offset,这种组织和处理策略提供了如下好处:

  · 消费者可以根据需求,灵活指定offset消费。
  · 保证了消息不变性,为并发消费提供了线程安全的保证。每个consumer都保留自己的offset,互相之间不干扰,不存在线程安全问题。
  · 消息访问的并行高效性。每个topic中的消息被组织成多个partition,partition均匀分配到集群server中。生产、消费消息的时候,会被路由到指定partition,减少竞争,增加了程序的并行能力。
  · 增加消息系统的可伸缩性。每个topic中保留的消息可能非常庞大,通过partition将消息切分成多个子消息,并通过负责均衡策略将partition分配到不同server。这样当机器负载满的时候,通过扩容可以将消息重新均匀分配。
  · 保证消息可靠性。消息消费完成之后不会删除,可以通过重置offset重新消费,保证了消息不会丢失。
  · 灵活的持久化策略。可以通过指定时间段(如最近一天)来保存消息,节省broker存储空间。
  · 备份高可用性。消息以partition为单位分配到多个server,并以partition为单位进行备份。备份策略为:1个leader和N个followers,leader接受读写请求,followers被动复制leader。leader和followers会在集群中打散,保证partition高可用。

3、Partitions

       每个Topics划分为一个或者多个Partition,并且Partition中的每条消息都被标记了一个sequential id ,也就是offset,并且存储的数据是可配置存储时间的 

4、producer

producer生产消息需要如下参数:

  •  topic:往哪个topic生产消息。
  •  partition:往哪个partition生产消息。
  •  key:根据该key将消息分区到不同partition。
  •  message:消息。

5、consumer
传统消息系统有两种模式:

 队列
 发布订阅
kafka通过consumer group将两种模式统一处理:每个consumer将自己标记consumer group名称,之后系统会将consumer group按名称分组,将消息复制并分发给所有分组,每个分组只有一个consumer能消费这条消息。如下图:

于是推理出两个极端情况:

  •  当所有consumer的consumer group相同时,系统变成队列模式
  •  当每个consumer的consumer group都不相同时,系统变成发布订阅

注意:

       1、Consumer Groups 提供了topics和partitions的隔离, 如上图Consumer Group A中的consumer-C2挂掉,consumer-C1会接收P1,P2,即一个consumer Group中有其他consumer挂掉后能够重新平衡。如下图:

 2、多consumer并发消费消息时,容易导致消息乱序,通过限制消费者为同步,可以保证消息有序,但是这大大降低了程序的并发性。

    kafka通过partition的概念,保证了partition内消息有序性,缓解了上面的问题。partition内消息会复制分发给所有分组,每个分组只有一个consumer能消费这条消息。这个语义保证了某个分组消费某个分区的消息,是同步而非并发的。如果一个topic只有一个partition,那么这个topic并发消费有序,否则只是单个partition有序。

一般消息系统,consumer存在两种消费模型:

 push:优势在于消息实时性高。劣势在于没有考虑consumer消费能力和饱和情况,容易导致producer压垮consumer。
 pull:优势在可以控制消费速度和消费数量,保证consumer不会出现饱和。劣势在于当没有数据,会出现空轮询,消耗cpu。
kafka采用pull,并采用可配置化参数保证当存在数据并且数据量达到一定量的时候,consumer端才进行pull操作,否则一直处于block状态。kakfa采用整数值consumer position来记录单个分区的消费状态,并且单个分区单个消息只能被consumer group内的一个consumer消费,维护简单开销小。消费完成,broker收到确认,position指向下次消费的offset。由于消息不会删除,在完成消费,position更新之后,consumer依然可以重置offset重新消费历史消息。
 

消息发送语义
producer视角

 消息最多发送一次:producer异步发送消息,或者同步发消息但重试次数为0。
 消息至少发送一次:producer同步发送消息,失败、超时都会重试。
 消息发且仅发一次:后续版本支持。
consumer视角

 消息最多消费一次:consumer先读取消息,再确认position,最后处理消息。
 消息至少消费一次:consumer先读取消息,再处理消息,最后确认position。
 消息消费且仅消费一次。
注意:

    如果消息处理后的输出端(如db)能保证消息更新幂等性,则多次消费也能保证exactly once语义。
    如果输出端能支持两阶段提交协议,则能保证确认position和处理输出消息同时成功或者同时失败。
    在消息处理的输出端存储更新后的position,保证了确认position和处理输出消息的原子性(简单、通用)。


可用性
    在kafka中,正常情况下所有node处于同步中状态,当某个node处于非同步中状态,也就意味着整个系统出问题,需要做容错处理。

同步中代表了:

     该node与zookeeper能连通。
     该node如果是follower,那么consumer position与leader不能差距太大(差额可配置)。
某个分区内同步中的node组成一个集合,即该分区的ISR。

kafka通过两个手段容错:

 数据备份:以partition为单位备份,副本数可设置。当副本数为N时,代表1个leader,N-1个followers,followers可以视为leader的consumer,拉取leader的消息,append到自己的系统中
 failover:
        1. 当leader处于非同步中时,系统从followers中选举新leader

       2. 当某个follower状态变为非同步中时,leader会将此follower剔除ISR,当此follower恢复并完成数据同步之后再次进入 ISR。

另外,kafka有个保障:当producer生产消息时,只有当消息被所有ISR确认时,才表示该消息提交成功。只有提交成功的消息,才能被consumer消费。

因此,当有N个副本时,N个副本都在ISR中,N-1个副本都出现异常时,系统依然能提供服务。

        假设N副本全挂了,node恢复后会面临同步数据的过程,这期间ISR中没有node,会导致该分区服务不可用。kafka采用一种降级措施来处理:选举第一个恢复的node作为leader提供服务,以它的数据为基准,这个措施被称为脏leader选举。由于leader是主要提供服务的,kafka broker将多个partition的leader均分在不同的server上以均摊风险。每个parition都有leader,如果在每个partition内运行选主进程,那么会导致产生非常多选主进程。kakfa采用一种轻量级的方式:从broker集群中选出一个作为controller,这个controller监控挂掉的broker,为上面的分区批量选主。

一致性
上面的方案保证了数据高可用,有时高可用是体现在对一致性的牺牲上。如果希望达到强一致性,可以采取如下措施:

     禁用脏leader选举,ISR没有node时,宁可不提供服务也不要未完全同步的node。
    设置最小ISR数量min_isr,保证消息至少要被min_isr个node确认才能提交。
持久化
基于以下几点事实,kafka重度依赖磁盘而非内存来存储消息。

     硬盘便宜,内存贵
     顺序读+预读取操作,能提高缓存命中率
     操作系统利用富余的内存作为pagecache,配合预读取(read-ahead)+写回(write-back)技术,从cache读数据,写到cache就返回(操作系统后台flush),提高用户进程响应速度
     java对象实际大小比理想大小要大,使得将消息存到内存成本很高
     当堆内存占用不断增加时,gc抖动较大
     基于文件顺序读写的设计思路,代码编写简单
     在持久化数据结构的选择上,kafka采用了queue而不是Btree
     kafka只有简单的根据offset读和append操作,所以基于queue操作的时间复杂度为O(1),而基于Btree操作的时间复杂度为O(logN)
     在大量文件读写的时候,基于queue的read和append只需要一次磁盘寻址,而Btree则会涉及多次。磁盘寻址过程极大降低了读写性能

五、Kafka的特性

(1)高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作;

(2)可扩展性:kafka集群支持热扩展;

(3)持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失;

(4)容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败);

(5)高并发:支持数千个客户端同时读写;

(6)支持实时在线处理和离线处理:可以使用Storm这种实时流处理系统对消息进行实时进行处理,同时还可以使用Hadoop这种批处理系统进行离线处理;

六、kafka的安装和使用

详情参考我的另外一篇博文:https://blog.csdn.net/qq_33371766/article/details/106652013

参考文章参考文章
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值