赞
踩
Apache Kafka 是分布式发布 - 订阅消息系统,在 kafka 官网上对 kafka 的定义:一个分布式发布 - 订阅消息传递系统。Kafka 最初由 LinkedIn 公司开发,Linkedin 于 2010 年贡献给了 Apache 基金会并成为顶级开源项目。
Kafka 的主要应用场景有:日志收集系统和消息系统。
Kafka是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写
Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。
Zookeeper是一个分布式的协调组件,早期版本的Kafka用Zookeeper做meta信息存储,consumer的消费状态,group的管理以及 offset的值。2021年4月,Kafka官方发布了2.8.0版本,宣布Kafka正式移除了对Zookeeper的依赖,这样就无需维护Zookeeper集群,只要维护Kafka集群
高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
高堆积:支持topic下消费者较长时间离线,消息堆积量大;
它被设计为⼀个分布式系统,易于向外扩展;
它同时为发布和订阅提供高吞吐量;
它⽀持多订阅者,当失败时能自动平衡消费者;
它将消息持久化到磁盘,因此可⽤于批量消费,例如ETL,以及实时应用程序。
快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化;
Kafka 是一个分布式流处理平台和消息系统,具有许多优点
Producer : 生产者,发送消息的一方
Consumer : 消费者,接收消息的一方
Broker : kafka节点,一个节点就是一个kafka server进程
Topic :主题,消息以主题来进行归类
Partition :分区,主题的所有消息分布在不同的区中,每个分区的消息一定是不同的,分区可以分布在不同的broker中
Replica : 副本机制,每个分区引入多副本,leader副本和follower副本,leader副本处理读写,follower副本负责同步leader副本的数据,出现故障时,follower副本中重新选举出新的leader副本,进行故障转移
ISR :
PacificA : kafka采用的一致性协议
消费模式
kafka中采用主动拉取模式,消费者主动从分区拉取消息
消费位移
为了保证重启之后或者有新的消费者加入到消费组后,能够正确地继续消费某个分区,因此会有消费位移的概念,每个消费者进行消费后,都会定时提交当前消费的位移
流平台具有三个关键功能:
消息队列:发布和订阅消息流,这个功能类似于消息队列,这也是 Kafka 也被归类为消息队列的原因。
容错的持久方式存储记录消息流: Kafka 会把消息持久化到磁盘,有效避免了消息丢失的风险。
流式处理平台: 在消息发布的时候进行处理,Kafka 提供了一个完整的流式处理类库。
当日志片段大小达到指定的数量的时候(默认为1G),当前日志片段就会被关闭,一个新的日志片段被打开。Kafka中消息是以 topic 进行分类的,生产、消费消息,都是面向 topic的,
topic是逻辑上的概念,而 partition 是物理上的概念,
每个partition对应于一个log文件,文件中存储的是producer生产的数据
Kafka采取了分片和索引机制,将每个partition分为多个segment
不同的Raplica的Offset是不一样的,这就需要Leader与Follower之间进行数据同步
从节点怎么跟主节点保持同步的过程:
Follower节点向Leader发送一个fetch请求,Leader向Follower发送数据后,随即更新Follower的LEO;
Follower接收到数据响应后,依次写入消息并且更新LEO;
Leader更新HW
Kafka这种独特的ISR复制,可以在保障数据一致性情况下又可提供高吞吐量。
Replica故障处理
Follower故障,Follower发生故障,会被先踢出ISR;
Kafka 只是分为一个或多个分区的主题的集合。Kafka 分区是消息的线性有序序列,其中每个消息由它们的索引(称为偏移)来标识。Kafka 集群中的所有数据都是不相连的分区联合。 传入消息写在分区的末尾,消息由消费者顺序读取。 通过将消息复制到不同的代理提供持久性。
Kafka 以快速,可靠,持久,容错和零停机的方式提供基于pub-sub 和队列的消息系统。 在这两种情况下,生产者只需将消息发送到主题,消费者可以根据自己的需要选择任何一种类型的消息传递系统。 让我们按照下一节中的步骤来了解消费者如何选择他们选择的消息系统。
以下是 Pub-Sub 消息的逐步工作流程
生产者定期向主题发送消息。
Kafka 代理存储为该特定主题配置的分区中的所有消息。 它确保消息在分区之间平等共享。 如果生产者发送两个消息并且有两个分区,Kafka 将在第一分区中存储一个消息,在第二分区中存储第二消息。
消费者订阅特定主题。
一旦消费者订阅主题,Kafka 将向消费者提供主题的当前偏移,并且还将偏移保存在 Zookeeper 系统中。
消费者将定期请求 Kafka (如100 Ms)新消息。
一旦 Kafka 收到来自生产者的消息,它将这些消息转发给消费者。
消费者将收到消息并进行处理。
一旦消息被处理,消费者将向 Kafka 代理发送确认。
一旦 Kafka 收到确认,它将偏移更改为新值,并在 Zookeeper 中更新它。 由于偏移在 Zookeeper 中维护,消费者可以正确地读取下一封邮件,即使在服务器暴力期间。
以上流程将重复,直到消费者停止请求。
消费者可以随时回退/跳到所需的主题偏移量,并阅读所有后续消息
队列消息/用户组的工作流
在队列消息传递系统而不是单个消费者中,具有相同组 ID 的一组消费者将订阅主题。 简单来说,订阅具有相同 Group ID 的主题的消费者被认为是单个组,并且消息在它们之间共享。 让我们检查这个系统的实际工作流程。
生产者以固定间隔向某个主题发送消息。
Kafka存储在为该特定主题配置的分区中的所有消息,类似于前面的方案。
单个消费者订阅特定主题,假设 Topic-01 为 Group ID 为 Group-1 。
Kafka 以与发布 - 订阅消息相同的方式与消费者交互,直到新消费者以相同的组 ID 订阅相同主题Topic-01 1 。
一旦新消费者到达,Kafka 将其操作切换到共享模式,并在两个消费者之间共享数据。 此共享将继续,直到用户数达到为该特定主题配置的分区数。一旦消费者的数量超过分区的数量,新消费者将不会接收任何进一步的消息,直到现有消费者取消订阅任何一个消费者。 出现这种情况是因为 Kafka 中的每个消费者将被分配至少一个分区,并且一旦所有分区被分配给现有消费者,新消费者将必须等待。
此功能也称为使用者组。 同样,Kafka 将以非常简单和高效的方式提供两个系统中最好的。
确实Kafka早期的版本就是直接用Zookeeper来完成选举的。利用了Zookeeper的Watch机制;节点不允许重复写入以及临时节点这些特性。这样实现比较简单,省事。但是也会存在一定的弊端。比如分区和副本数量过多,所有的副本都直接参与选举的话,一旦某个出现节点的增减,就会造成大量的Watch事件被触发,ZooKeeper的就会负载过重,不堪重负。
新版本的Kafka中换了一种实现方式。不是所有的Repalica都参与Leader选举,而是由其中的一个Broker统一来指挥,这个Broker的角色就叫做Controller控制器。Kafka要先从所有Broker中选出唯一的一个Controller。
所有的Broker会尝试在Zookeeper中创建临时节点/controller,谁先创建成功,谁就是Controller。那如果Controller挂掉或者网络出现问题,ZooKeeper上的临时节点就会消失。其他的Broker通过Watch监听到Controller下线的消息后,继续按照先到先得的原则竞选Controller。这个Controller就相当于选举委员会的主席。当一个节点成为Controller之后,他就会承担以下职责:
监听Broker变化、监听Topic变化、监听Partition变化、获取和管理Broker、Topic、Partition的信息、管理Partiontion的主从信息。
选举规则
Controller确定以后,就可以开始做分区选主的事情。接下来就是找候选人。显然,每个Replica都想推荐自己,但不是所有的Replica都有竞选资格。只有在ISR(In-Sync Replicas)保持心跳同步的副本才有资格参与竞选。就好比是皇帝每天着急皇子们开早会,只有每天来打卡的皇子才能加入ISR。那些请假的、迟到的没有资格参与选举。接下来,就是Leader选举,就相当于要在众多皇子中选出太子。在分布式选举中,有非常多的选举协议比如ZAB、Raft等等,他们的思想归纳起来都是:先到先得,少数服从多数。但是Kafka没有用这些方法,而是用了一种自己实现的算法。提到Kafka官方的解释是,它的选举算法和微软的PacificA算法最相近。大致意思就是,默认是让ISR中第一个Replica变成Leader。比如ISR是1、5、9,优先让1成为Leader。这个跟中国古代皇帝传位是一样的,优先传给皇长子。这样设计的好处是可以提高数据副本的容灾能力。将Leader和副本完全错开,从而不至于一挂全挂。
1、越多的分区可以提供更高的吞吐量
2、越多的分区需要打开更多的文件句柄
3、越多的分区会导致消费者消费的延迟越高
4、越多的分区意味着需要更多的内存
5、越多的partition会导致更长时间的恢复期
request.required.acks有三个值 0 1 -1
0:生产者不会等待broker的ack,这个延迟最低但是存储的保证最弱当server挂掉的时候就会丢数据
ack=0: 不管kafka的partition状态,只往里面发数据,因为不获取kafka分区的回调信息
1:服务端会等待ack值 leader副本确认接收到消息后发送ack但是如果leader挂掉后他不确保是否复制完成新leader也会导致数据丢失
ack=1: 往kafka发数据,只要有leader存活(broker抢到controller),就往kafka发数据,因为需要partition返回确认信息
-1:同样在1的基础上 服务端会等所有的follower的副本受到数据后才会受到leader发出的ack,这样数据不会丢失
ack=-1: 往kafaka发数据,当发数据的时候出现网络波动、副本或者主机死掉,那么会出现短暂的卡顿,之后会正常发数据,因为ack=-1需要所有的ISR返回ok信息,如果没有返回的会把该副本T出ISR
Kafka 主要有两大应用场景:
消息队列 :建立实时流数据管道,以可靠地在系统或应用程序之间获取数据。
数据处理: 构建实时的流数据处理程序来转换或处理数据流
1.大数据流数据处理
2.elk日志收集
日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、HBase、Solr等。
消息系统:解耦和生产者和消费者、缓存消息等。
用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
流式处理:比如spark streaming和 Flink
对于⼀些常规的消息系统,kafka是个不错的选择;partitons/replication和容错,可以使kafka具有良好的扩展性和性能优势.
不过到目前为止,我们应该很清楚认识到,kafka并没有提供JMS中的"事务性"“消息传输担保(消息确认机制)”“消息分组"等企业级特性;
kafka只能使用作为"常规"的消息系统,在⼀定程度上,尚未确保消息的发送与接收绝对可靠(⽐如,消息重发,消息发送丢失等)
kafka的特性决定非常适合作为"日志收集中心”;application可以将操作⽇志"批量""异步"的发送到kafka集群中,
⽽不是保存在本地或者DB中;kafka可以批量提交消息/压缩消息等,这对producer端而言,几乎感觉不到性能的开⽀.
consumer端采⽤批量fetch方式,此时consumer端也可以使hadoop等其他系统化的存储和分析系统
数据传输的事务定义通常有以下三种级别:
(1)最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输
(2)最少一次: 消息不会被漏发送,最少被传输一次,但也有可能被重复传输.
(3)精确的一次(Exactly once): 不会漏传输也不会重复传输,每个消息都传输被一次而且仅仅被传输一次,这是大家所期望的
Kafka判断一个节点是否还活着有那两个条件
(1)节点必须可以维护和ZooKeeper的连接,Zookeeper通过心跳机制检查每个节点的连接
(2)如果节点是个follower,他必须能及时的同步leader的写操作,延时不能太久
producer直接将数据发送到broker的leader(主节点),不需要在多个节点进行分发,为了帮助producer做到这点,所有的Kafka节点都可以及时的告知:哪些节点是活动的,目标topic目标分区的leader在哪。这样producer就可以直接将消息发送到目的地了
Kafa consumer是否可以消费指定分区消息?
Kafa consumer消费消息时,向broker发出"fetch"请求去消费特定分区的消息,consumer指定消息在日志中的偏移量(offset),就可以消费从这个位置开始的消息,customer拥有了offset的控制权,可以向后回滚去重新消费之前的消息,这是很有意义的
Kafka最初考虑的问题是,customer应该从brokes拉取消息还是brokers将消息推送到consumer,也就是pull还push。在这方面,Kafka遵循了一种大部分消息系统共同的传统的设计:producer将消息推送到broker,consumer从broker拉取消息
一些消息系统比如Scribe和Apache Flume采用了push模式,将消息推送到下游的consumer。这样做有好处也有坏处:由broker决定消息推送的速率,对于不同消费速率的consumer就不太好处理了。消息系统都致力于让consumer以最大的速率最快速的消费消息,但不幸的是,push模式下,当broker推送的速率远大于consumer消费的速率时,consumer恐怕就要崩溃了。最终Kafka还是选取了传统的pull模式
Pull模式的另外一个好处是consumer可以自主决定是否批量的从broker拉取数据。Push模式必须在不知道下游consumer消费能力和消费策略的情况下决定是立即推送每条消息还是缓存之后批量推送。如果为了避免consumer崩溃而采用较低的推送速率,将可能导致一次只推送较少的消息而造成浪费。Pull模式下,consumer就可以根据自己的消费能力去决定这些策略
Pull有个缺点是,如果broker没有可供消费的消息,将导致consumer不断在循环中轮询,直到新消息到t达。为了避免这点,Kafka有个参数可以让consumer阻塞知道新消息到达(当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量发
消息由一个固定长度的头部和可变长度的字节数组组成。头部包含了一个版本号和CRC32校验码。
消息长度: 4 bytes (value: 1+4+n)
版本号: 1 byte
CRC校验码: 4 bytes
具体的消息: n bytes
(1).Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
(2).通过索引信息可以快速定位message和确定response的最大大小。
(3).通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
(4).通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。
Kafka 与传统消息系统之间有三个关键区别
(1).Kafka 持久化日志,这些日志可以被重复读取和无限期保留
(2).Kafka 是一个分布式系统:它以集群的方式运行,可以灵活伸缩,在内部通过复制数据提升容错能力和高可用性
(3).Kafka 支持实时的流式处理
副本因子不能大于 Broker 的个数;
第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的;
其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推;
剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的
在启动 Kafka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kafka 数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性能。
当然我们也可以配置 log.dir 参数,含义一样。只需要设置其中一个即可。
如果 log.dirs 参数只配置了一个目录,那么分配到各个 Broker 上的分区肯定只能在这个目录下创建文件夹用于存放数据。
但是如果 log.dirs 参数配置了多个目录,那么 Kafka 会在哪个文件夹中创建分区目录呢?答案是:Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic名+分区ID。注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就是说,如果你给 log.dirs 参数新增了一个新的磁盘,新的分区目录肯定是先在这个新的磁盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。
topic中的多个partition以文件夹的形式保存到broker,每个分区序号从0递增,且消息有序
Partition文件下有多个segment(xxx.index,xxx.log)
segment 文件里的 大小和配置文件大小一致可以根据要求修改 默认为1g
如果大小大于1g时,会滚动一个新的segment并且以上一个segment最后一条消息的偏移量命名
消费者每次消费数据的时候,消费者都会记录消费的物理偏移量(offset)的位置,等到下次消费时,他会接着上次位置继续消费
消费者负载均衡策略
一个消费者组中的一个分片对应一个消费者成员,他能保证每个消费者成员都能访问,如果组中成员太多会有空闲的成员
一个消费者组里它的内部是有序的
消费者组与消费者组之间是无序的
kafaka生产数据时数据的分组策略
生产者决定数据产生到集群的哪个partition中,每一条消息都是以(key,value)格式
Key是由生产者发送数据传入,所以生产者(key)决定了数据产生到集群的哪个partition
分区对于 Kafka 集群的好处是:实现负载均衡。分区对于消费者来说,可以提高并发度,提高效率,Kafka 可以将主题划分为多个分区(Partition),会根据分区规则选择把消息存储到哪个 分区中,只要分区规则设置的合理,那么所有的消息将会被均匀的分布到不同的分区中,
这样就实现了负载均衡和水平扩展。另外,多个订阅者可以从一个或者多个分区中同时消
费数据,以支撑海量数据处理能力。 producer 只需要关心消息发往哪个 topic,而 consumer 只关心自己订阅哪个 topic,并 不关心每条消息存于整个集群的哪个 broker。 为了性能考虑,如果 topic 内的消息只存 于一个 broker,那这个 broker 会成为瓶颈,无法做到水平扩展。所以把 topic 内的数据 分布到整个集群就是一个自然而然的设计方式。 Partition 的引入就是解决水平扩展问题的一个方案。
还有一点我觉得比较重要的是 Kafka 为分区(Partition)引入了多副本(Replica)机制。分区(Partition)中的多个副本之间会有一个叫做 leader 的家伙,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。
生产者和消费者只与 leader 副本交互。你可以理解为其他副本只是 leader 副本的拷贝,它们的存在只是为了保证消息存储的安全性。当 leader 副本发生故障时会从 follower 中选举出一个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。
Kafka 的多分区(Partition)以及多副本(Replica)机制有什么好处
在 Kafka 中,可以通过以下几种方式来确保消息只被消费一次:
Kafka的重平衡(rebalancing)机制是指在Kafka消费者群组中,当消费者实例的数量发生变化时(如新增或减少消费者实例),Kafka会自动重新分配分区(partitions)给各个消费者实例,以保证每个分区只被一个消费者实例消费。重平衡机制确保了消费者群组的负载均衡和高可用性。
具体来说,Kafka的重平衡机制包括以下几个关键点:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。