消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统。
消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。
通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。
Kafka 是一个分布式的流式处理平台,它以高吞吐、可持久化、可水平扩展、支持流数据处理等多种特性而被广泛使用。
主要功能体现在以下 3 点:
一个典型的 Kafka 体系架构包括若干 Producer、若干 Consumer、以及一个 ZooKeeper 集群。
注意:在 2.8.0 版本中,Kafka 移除了 Zookeeper,通过 KRaft 进行集群管理。
Producer 将消息发送到 Broker,Broker 负责将受到的消息存储到磁盘中,而 Consumer 负责从 Broker 订阅并消费消息。
Kafka 基本概念:
leader 负责维护和跟踪 ISR 集合中所有 follower 副本的滞后状态。
当 follower 副本落后过多时,就会将其放入 OSR 集合。
当 follower 副本追上了 leader 的进度时,就会将其放入 ISR 集合。
默认情况下,只有 ISR 中的副本才有资格晋升为 leader。
分区相当于一个日志文件。我们先简单介绍几个概念:
上图是一个分区日志文件:
分区 ISR 集合中的每个副本都会维护自己的 LEO,而 ISR 集合中最小的 LEO 即为分区的 HW。
如上图所示,3 个分区副本都是 ISR 集合当中的。最小的 LEO 为 3,就代表分区的 HW 为3。
所以,当前分区只能消费到 0~2 之间的 3 条数据,如下图:
总共有 3 种模式:
1. 发后即忘(fire-and-forget) 它只管往 Kafka 里面发送消息,但是不关心消息是否正确到达。 这种方式的效率最高,但是可靠性也最差,比如当发生某些不可充实异常的时候会造成消息的丢失。 2. 同步(sync) producer.send() 返回一个 Future 对象,调用 get() 方法变回进行同步等待就知道消息是否发送成功。 发送一条消息需要等上个消息发送成功后才可以继续发送。 3. 异步(async) Kafka支持 producer.send() 传入一个回调函数,消息不管成功或者失败都会调用这个回调函数,这样就算是异步发送。 我们也知道消息的发送情况,然后再回调函数中选择记录日志还是重试都取决于调用方。
1. 轮询
依次将消息发送至该 topic 下的所有分区。如果在创建消息的时候 key 为 null,Kafka 默认采用这种策略。
2. key 指定分区
创建消息时 key 不为空并且使用默认分区器,Kafka 会将 key 进行 hash,然后根据 hash 值映射到指定的分区上。这样的好处是 key 相同的消息会在一个分区下。
Kafka 并不能保证全局有序,但是在每个分区下的消息是有序的。按照顺序存储,按照顺序消费。在保证同一个 key 的消息是有序的,这样基本能满足消息的顺序性的需求。但是如果 partation 数量发生变化,那就很难保证 key 与分区之间的映射关系了。
3. 自定义策略
实现 Partitioner 接口就能自定义分区策略。
4. 指定 Partiton 发送
Kafka 是不支持读写分离的,那么读写分离的好处是什么?
主要就是让一个节点去承担另一个节点的负载压力,也就是能做到一定程度的负载均衡,而且 Kafka 不通过读写分离也可以一定程度上去实现负载均衡。
但是对于 Kafka 的架构来说,读写分离有两个很大的缺点:
1. 数据不一致的问题
读写分离必然涉及到数据的同步,只要是不同节点之间的数据同步,必然会有数据不一致的问题存在。
2. 延时问题
由于 Kafka 独特的数据处理方式,导致如果将数据从一个节点同步到另一个节点必然会经过主节点磁盘和从节点磁盘。对一些延时性要求较高的应用来说,不太适用。
Kafka 的负责均衡主要是通过分区来实现的。我们知道 Kafka 是主写主读的架构,如下图:
共 3 个 broker ,里面各有 3 个副本总共有 3 个 partation。
深色的是 leader,浅色的是 follower,上下灰色分别代表生产者和消费者,虚线代表 follower 从 leader 拉取消息。
从这张图就可以很明显的看出:每个 broker 都有消费者拉取消息,每个 broker 也都有生产者发送消息,每个 broker 上的读写负载都是一样的。这也说明了 kafka 独特的架构方式可以通过主写主读来实现负载均衡。
Kafka 的负载均衡在绝对理想的状况下可以实现,但是会有某些情况出现一定程度上的负载不均衡。
1. broker 端分配不均匀
当创建 topic 的时候可能会出现某些 broker 分配到的分区数多,而有些 broker 分配的分区少,这就导致了 leader 多副本不均。
2. 生产者写入消息不均匀
生产者可能只对某些 broker 中的 leader 副本进行大量的写入操作,而对其他的 leader 副本不闻不问。
3. 消费者消费不均匀
消费者可能只对某些 broker 中的 leader 副本进行大量的拉取操作,而对其他的 leader 副本不闻不问。
4. leader 副本切换不均
当主从副本切换或者分区副本进行了重分配后,可能会导致各个 broker 中的 leader 副本分配不均匀。
1. acks
这个参数用来指定分区中有多少个副本收到这条消息,生产者才认为这条消息是写入成功的。
这个参数有 3 个值:
2. 消息发送的方式
第 6 问中我们提到了生产者发送消息有三种方式,发完即忘、**同步和异步**。我们可以通过同步或者异步获取响应结果,失败做重试来保证消息的可靠性。
3. 手动提交位移
默认情况下,当消费者消费到消息后就会自动提交位移。
但是如果消费者消费出错,没有进入真正的业务处理,那么就可能会导致这条消息消费失败,从而丢失。
我们可以开启手动提交位移,等待业务正常处理完成后,再提交 offset。
4. 通过副本 LEO 来确定分区 HW
可参考第 5 问。
一般消息消费有两种模式:推和拉。
Kafka 的消费是属于“拉”模式的。因此模式的消息消费方式有两种,点对点和发布订阅。
1. 点对点
如果所有消费者属于同一个消费组,那么所有的消息都会被均匀的投递给每一个消费者,每条消息只会被其中一个消费者消费。
2. 发布订阅
如果所有消费者属于不同的消费组,那么所有的消息都会被投递给每一个消费者,每个消费者都会收到该消息。
分区再分配主要是用来维护 Kafka 集群的负载均衡。
既然是分区再分配,那么 Kafka 分区有什么问题呢?
问题 1、当集群中的一个节点下线了
如果该节点的分区是单副本,那么分区将会变得不可用。如果是多副本,就会进行 leader 选举,在其他机器上选举出新的 leader。
Kafka 并不会将这些失效的分区迁移到其他可用的 broker 上,这样就会影响集群的负载均衡。甚至也会影响服务的可靠性和可用性。
问题2、集群新增 broker
只有新的主题分区会分配在该 broker 上,而老的主题分区不会分配在该 broker 上。这样就造成了老节点和新节点之间的负载不均衡。为了解决该问题就出现了分区再分配,它可以在集群扩容。broker 失效的场景下进行分区迁移。
分区再分配的原理就是通化控制器给分区新增新的副本,然后通过网络把旧的副本数据复制到新的副本上。当复制完成后,将旧副本清除。
当然,为了不影响集群正常的性能,在此复制期间还会有一些列保证性能的操作,比如复制限流。
当分区 leader 节点崩溃时,其中一个 follower 节点会成为新的 leader 节点,这样会导致集群的负载不均衡,从而影响服务的健壮性和稳定性。
像下面这样的情况:
Topic: test Partation:0 Leader:1 Replicas:1,2,0 Isr:1,2,0
Topic: test Partation:1 Leader:2 Replicas:2,0,1 Isr:2,0,1
Topic: test Partation:2 Leader:0 Replicas:0,1,2 Isr:0,1,2
我们可以看到:
如果此时中间的节点重启:
Topic: test Partation:0 Leader:1 Replicas:1,2,0 Isr:1,0,2
Topic: test Partation:1 Leader:0 Replicas:2,0,1 Isr:0,1,2
Topic: test Partation:2 Leader:0 Replicas:0,1,2 Isr:0,1,2
我们又可以看到:
我们会发现,原本 1 分区有两个 ledaer,经过重启后 leader 都消失了。这样打破了负载均衡。
为了解决这种问题,就引入了优先副本的概念。
优先副本就是说在 AR 集合中的第一个副本。比如分区 2 的 AR 为 0,1,2,那么分区 2 的优先副本就为0。理想情况下优先副本就是 leader 副本。
优先副本选举就是促使优先副本成为 leader 副本,从而维护集群的负载均衡。
一般类似于这种问题的答案,都是持否定态度的。
但是可以说,在一定条件下分区数的数量是和吞吐量成正比的,分区数和性能也是成正比的。
那么为什么说超过了一定限度就会对性能造成影响呢?原因如下:
1. 客户端/服务器端需要使用的内存就越多
2. 文件句柄的开销
每个 partition 都会对应磁盘文件系统的一个目录。在 Kafka 的数据日志文件目录中,每个日志数据段都会分配两个文件,一个索引文件和一个数据文件。每个 broker 会为每个日志段文件打开一个 index 文件句柄和一个数据文件句柄。
因此,随着 partition 的增多所需要保持打开状态的文件句柄数也就越多。最终可能超过底层操作系统配置的文件句柄数量限制。
3. 越多的分区可能增加端对端的延迟
Kafka 会将分区 HW 之前的消息暴露给消费者。分区越多则副本之间的同步数量就越多。
在默认情况下,每个 broker 从其他 broker 节点进行数据副本复制时,该 broker 节点只会为此工作分配一个线程。该线程需要完成该 broker 所有 partition 数据的复制。
4. 降低高可用性
在第 13 问我们提到了分区再分配,会将数据复制到另一份副本当中。分区数量越多,那么恢复时间也就越长。
而如果发生宕机的 broker 恰好是 controller 节点时,在这种情况下新 leader 节点的选举过程在 controller 节点恢复到新的 broker 之前不会启动。controller 节点的错误恢复将会自动地进行,但是新的 controller 节点需要从 zookeeper 中读取每一个 partition 的元数据信息用于初始化数据。
假设一个 Kafka 集群存在 10000个partition,从 ZooKeeper 中恢复元数据时每个 partition 大约花费 2ms,则 controller 的恢复将会增加约 20 秒的不可用时间窗口。
1. RangeAssignor 分配策略
该分配策略是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后分区按照跨度来进行平均分配,尽可能保证分区均匀的分配给所有的消费者。
对于每个 topic,该策略会讲消费者组内所有订阅这个主题的消费者按照名称的字典顺序排序,然后为每个消费者划分固定过的区域,如果不够平均分配,那么字典排序考前的就会多分配一个分区。
比如 2 个消费者属于一个消费者组,有 2 个 topic t1,t2,每个 topic 都有 3 个分区,p1,p2,p3,那么分配的情况如下:
消费者 A: t0-p0,t0-p1,t1-p0,t1-p1,
消费者 B: t0-p2,t1-p2
这样就会出现分配不均匀的情况。
2. RoundRobinAssignor 分配策略
该分配策略是按将消费者组内所有消费者及消费者订阅的所有主题的分区按照字典排序,然后通过轮询的方式分配给每个消费者。
比如有 3 个消费者 A,B,C,订阅了 3 个 topic ,t0,t1,t2,每个 topic 各有 3 个分区 p0,p1,p2。如果 A 订阅了 t0,B 订阅了 t0 和 t1,C 订阅了 t0,t1,t2,那么分配的情况如下:
消费者 A: t0-p0
消费者 B: t1-p0
消费者 C: t1-p1,t2-p0,t2-p1,t2-p2
这样也会出现分配不均匀的情况,按照订阅情况来讲完全可以吧 t1p1 分配给消费者 B。
3. StickyAssignor 分配策略
这种分配策略有两个目的:
当两者发生冲突时,第一个目标优先于第二个目标。
假设消费组内有 3 个消费者:C0、C1、C2 它们都订阅了 4 个主题:t0、t1、t2、t3 并且每个主题有 2 个分区,也就是说整个消费组订阅了 t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3p1 这 8 个分区
最终的分配结果如下:
消费者 C0: t0p0、t1p1、t3p0
消费者 C1: t0p1、t2p0、t3p1
消费者 C2: t1p0、t2p1
这样初看上去似乎与采用 RoundRobinAssignor 策略所分配的结果相同。
此时假设消费者 C1 脱离了消费组,那么消费组就会执行再平衡操作,进而消费分区会重新分配。如果采用 RoundRobinAssignor 策略,那么此时的分配结果如下:
消费者 C0:t0p0、t1p0、t2p0、t3p0
消费者 C2:t0p1、t1p1、t2p1、t3p1
如分配结果所示,RoundRobinAssignor 策略会按照消费者 C0 和 C2 进行重新轮询分配。而如果此时使用的是 StickyAssignor 策略,那么分配结果为:
消费者 C0:t0p0、t1p1、t3p0、t2p0
消费者 C2:t1p0、t2p1、t0p1、t3p1
可以看到分配结果中保留了上一次分配中对于消费者 C0 和 C2 的所有分配结果,并将原来消费者 C1 的“负担”分配给了剩余的两个消费者 C0 和 C2,最终 C0 和 C2 的分配还保持了均衡。
如果发生分区重分配,那么对于同一个分区而言有可能之前的消费者和新指派的消费者不是同一个,对于之前消费者进行到一半的处理还要在新指派的消费者中再次复现一遍,这显然很浪费系统资源。StickyAssignor 策略如同其名称中的 “sticky” 一样,让分配策略具备一定的“粘性”,尽可能地让前后两次分配相同,进而减少系统资源的损耗以及其它异常情况的发生。
到目前为止所分析的都是消费者的订阅信息都是相同的情况,我们来看一下订阅信息不同的情况下的处理。
举例:同样消费组内有 3 个消费者:C0、C1、C2
集群中有 3 个主题 t0、t1、t2 这 3 个主题分别有 1、2、3个分区 也就是说集群中有 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2 这 6 个分区
消费者 C0 订阅了主题 t0,消费者 C1 订阅了主题 t0 和 t1,消费者 C2 订阅了主题 t0、t1 和 t2。
如果此时采用 RoundRobinAssignor 策略:
消费者C0:t0p0
消费者C1:t1p0
消费者C2:t1p1、t2p0、t2p1、t2p2
如果此时采用的是 StickyAssignor 策略:
消费者C0:t0p0
消费者C1:t1p0、t1p1
消费者C2:t2p0、t2p1、t2p2
此时消费者 C0 脱离了消费组,那么 RoundRobinAssignor 策略的分配结果为:
消费者C1:t0p0、t1p1
消费者C2:t1p0、t2p0、t2p1、t2p2
StickyAssignor 策略,那么分配结果为:
消费者C1:t1p0、t1p1、t0p0
消费者C2:t2p0、t2p1、t2p2
可以看到 StickyAssignor 策略保留了消费者 C1 和 C2 中原有的 5 个分区的分配:
t1p0、t1p1、t2p0、t2p1、t2p2
从结果上看 StickyAssignor 策略比另外两者分配策略而言显得更加的优异,这个策略的代码实现也是异常复杂。
4. 自定义分区分配策略
可以通过实现 org.apache.kafka.clients.consumer.internals.PartitionAssignor 接口来实现
在 Kafka 集群中会有一个或多个 broker,其中有一个 broker 会被选举为控制器,它负责管理整个集群中所有分区和副本的状态,Kafka 集群中只能有一个控制器。
Kafka 中的控制器选举工作依赖于 ZooKeeper,成功竞选成为控制器的 broker 会在Zookeeper中创建 /controller临时节点。
每个 broker 启动的时候会去尝试读取 /controller 节点的 brokerid 的值。
每个 broker 都会在内存中保存当前控制器的 brokerid 值,这个值可以标识为 activeControllerId。
ZooKeeper 中还有一个与控制器有关的 /controller_epoch 节点,这个节点是持久节点,节点中存放的是一个整型的 controller_epoch 值。controller_epoch 值用于记录控制器发生变更的次数。
controller_epoch 的初始值为1,即集群中的第一个控制器的纪元为 1,当控制器发生变更时,每选出一个新的控制器就将该字段值加1。
每个和控制器交互的请求都会携带 controller_epoch 这个字段,
1. 顺序读写
磁盘分为顺序读写与随机读写,基于磁盘的随机读写确实很慢,但磁盘的顺序读写性能却很高,kafka 这里采用的就是顺序读写。
2. Page Cache
为了优化读写性能,Kafka 利用了操作系统本身的 Page Cache,就是利用操作系统自身的内存而不是JVM空间内存。
3. 零拷贝
Kafka使用了零拷贝技术,也就是直接将数据从内核空间的读缓冲区直接拷贝到内核空间的 socket 缓冲区,然后再写入到 NIC 缓冲区,避免了在内核空间和用户空间之间穿梭。
4. 分区分段+索引
Kafka 的 message 是按 topic分 类存储的,topic 中的数据又是按照一个一个的 partition 即分区存储到不同 broker 节点。每个 partition 对应了操作系统上的一个文件夹,partition 实际上又是按照segment分段存储的。
通过这种分区分段的设计,Kafka 的 message 消息实际上是分布式存储在一个一个小的 segment 中的,每次文件操作也是直接操作的 segment。为了进一步的查询优化,Kafka 又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度。
5. 批量读写
Kafka 数据读写也是批量的而不是单条的,这样可以避免在网络上频繁传输单个消息带来的延迟和带宽开销。假设网络带宽为10MB/S,一次性传输10MB的消息比传输1KB的消息10000万次显然要快得多。
6. 批量压缩
Kafka 把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络 IO 损耗,通过 mmap 提高 I/O 速度,写入数据的时候由于单个Partion是末尾添加所以速度最优;读取数据的时候配合 sendfile 进行直接读取。
Kafka 有三次消息传递的过程:生产者发消息给 Broker,Broker 同步消息和持久化消息,Broker 将消息传递给消费者。
这其中每一步都有可能丢失消息。
1. 生产者发送数据
在第 11 问中的 acks 中有说到:
2. Broker 存储数据
kafka 通过 Page Cache 将数据写入磁盘。
Page Cache 就是当往磁盘文件写入的时候,系统会先将数据流写入缓存中,但是什么时候将缓存的数据写入文件中是由操作系统自行决定。所以如果此时机器突然挂了,也是会丢失消息的。
3. 消费者消费数据
在开启自动提交 offset 时,只要消费者消费到消息,那么就会自动提交偏移量,如果业务还没有来得及处理,那么消息就会丢失。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/Zp8J4taIgJTaiYjGpoNfxQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。