共计 6186 个字符,预计需要花费 16 分钟才能阅读完成。
那些年咱们用过的消息中间件 -kafka
为什么须要音讯队列
周末无聊刷着手机,某宝网 APP 忽然蹦出来一条音讯“为了回馈老客户,女朋友买一送一,流动仅限明天!”。
买一送一还有这种坏事,那我可不能错过!忍不住立马点了去。于是选了两个最新款,下单、领取零打碎敲!满足的躺在床上,想着马上有女朋友了,居然幸福的失眠了……
第二天失常上着班,忽然接到快递小哥的电话:
小哥:“你是 xx 吗?你的女朋友到了,我当初在你楼下,你来拿一下吧!”。\
我:“这……我在下班呢,能够早晨送过来吗?“。\
小哥:“早晨可不行哦,早晨我也上班了呢!”。
于是两个人僵持了很久……
最初小哥说,要不我帮你放到楼下小芳便利店吧,你早晨上班了过去拿,难堪的场面这才得以缓解!
回到正题,如果没有小芳便利店,那快递小哥和我的交互图就应该如下:
会呈现什么状况呢?
1、为了这个女朋友,我销假回去拿(老板不批)。
2、小哥始终在你楼下等(小哥还有其余的快递要送)。
3、周末再送(显然等不及)。
4、这个女朋友我不要了(相对不可能)!
小芳便利店呈现后,交互图就应如下:
在下面例子中,“快递小哥”和“买女朋友的我”就是须要交互的两个零碎,小芳便利店就是咱们本文要讲的 -“消息中间件”。总结下来小芳便利店(消息中间件)呈现后有如下益处:
1、解耦
快递小哥手上有很多快递须要送,他每次都须要先电话一一确认收货人是否有空、哪个时间段有空,而后再确定好送货的计划。这样齐全依赖收货人了!如果快递一多,快递小哥预计的忙疯了……如果有了便利店,快递小哥只须要将同一个小区的快递放在同一个便利店,而后告诉收货人来取货就能够了,这时候快递小哥和收货人就实现理解耦!
2、异步
快递小哥打电话给我后须要始终在你楼下等着,直到我拿走你的快递他能力去送其他人的。快递小哥将快递放在小芳便利店后,又能够干其余的活儿去了,不须要期待你到来而始终处于期待状态。进步了工作的效率。
3、削峰
假如双十一我买了不同店里的各种商品,而凑巧这些店发货的快递都不一样,有中通、圆通、申通、各种通等……更巧的是他们都同时到货了!中通的小哥打来电话叫我去北门取快递、圆通小哥叫我去南门、申通小哥叫我去东门。我一时慌手慌脚……
咱们能看到在零碎须要交互的场景中,应用音讯队列中间件真的是好处多多,基于这种思路,就有了丰巢、菜鸟驿站等比小芳便利店更业余的“中间件”了。
最初,下面的故事纯属虚构……
音讯队列通信的模式
通过下面的例子咱们引出了消息中间件,并且介绍了音讯队列呈现后的益处,这里就须要介绍音讯队列通信的两种模式了:
一、点对点模式
如上图所示,点对点模式通常是基于拉取或者轮询的音讯传送模型,这个模型的特点是发送到队列的音讯被一个且只有一个消费者进行解决。生产者将音讯放入音讯队列后,由消费者被动的去拉取音讯进行生产。点对点模型的的长处是消费者拉取音讯的频率能够由本人管制。然而音讯队列是否有音讯须要生产,在消费者端无奈感知,所以在消费者端须要额定的线程去监控。
二、公布订阅模式
如上图所示,公布订阅模式是一个基于音讯送的音讯传送模型,改模型能够有多种不同的订阅者。生产者将音讯放入音讯队列后,队列会将音讯推送给订阅过该类音讯的消费者。因为是消费者被动接管推送,所以无需感知音讯队列是否有待生产的音讯!然而 consumer1、consumer2、consumer3 因为机器性能不一样,所以解决音讯的能力也会不一样,但音讯队列却无奈感知消费者生产的速度!所以推送的速度成了公布订阅模模式的一个问题!假如三个消费者处理速度别离是 8M/s、5M/s、2M/s,如果队列推送的速度为 5M/s,则 consumer3 无奈接受!如果队列推送的速度为 2M/s,则 consumer1、consumer2 会呈现资源的极大节约!
Kafka
下面简略的介绍了为什么须要音讯队列以及音讯队列通信的两种模式,接下来就到了咱们本文的配角——kafka 闪亮退场的时候了!Kafka 是一种高吞吐量的分布式公布订阅音讯零碎,它能够解决消费者规模的网站中的所有动作流数据,具备高性能、长久化、多正本备份、横向扩大能力………
基础架构及术语
话不多说,先看图,通过这张图咱们来捋一捋相干的概念及之间的关系:
如果看到这张图你很懵逼,木有关系!
咱们先来剖析相干概念
Producer:Producer 即生产者,音讯的产生者,是音讯的入口。
kafka cluster:
Broker:Broker 是 kafka 实例,每个服务器上有一个或多个 kafka 的实例,咱们权且认为每个 broker 对应一台服务器。每个 kafka 集群内的 broker 都有一个不反复的编号,如图中的 broker-0、broker- 1 等……
Topic:音讯的主题,能够了解为音讯的分类,kafka 的数据就保留在 topic。在每个 broker 上都能够创立多个 topic。
Partition:Topic 的分区,每个 topic 能够有多个分区,分区的作用是做负载,进步 kafka 的吞吐量。同一个 topic 在不同的分区的数据是不反复的,partition 的表现形式就是一个一个的文件夹!
Replication: 每一个分区都有多个正本,正本的作用是做备胎。当主分区(Leader)故障的时候会抉择一个备胎(Follower)上位,成为 Leader。在 kafka 中默认正本的最大数量是 10 个,且正本的数量不能大于 Broker 的数量,follower 和 leader 相对是在不同的机器,同一机器对同一个分区也只可能寄存一个正本(包含本人)。
Message:每一条发送的音讯主体。
Consumer:消费者,即音讯的生产方,是音讯的进口。
Consumer Group:咱们能够将多个消费者组成一个消费者组,在 kafka 的设计中同一个分区的数据只能被消费者组中的某一个消费者生产。同一个消费者组的消费者能够生产同一个 topic 的不同分区的数据,这也是为了进步 kafka 的吞吐量!
Zookeeper:kafka 集群依赖 zookeeper 来保留集群的的元信息,来保证系统的可用性。
工作流程剖析
下面介绍了 kafka 的基础架构及基本概念,不晓得大家看完有没有对 kafka 有个大抵印象,如果对还比拟懵也没关系!咱们接下来再联合下面的结构图剖析 kafka 的工作流程,最初再回来整个梳理一遍我置信你会更有播种!
发送数据
咱们看下面的架构图中,producer 就是生产者,是数据的入口。留神看图中的红色箭头,Producer 在写入数据的时候 永远的找 leader,不会间接将数据写入 follower!那 leader 怎么找呢?写入的流程又是什么样的呢?咱们看下图:
发送的流程就在图中曾经阐明了,就不独自在文字列出来了!须要留神的一点是,音讯写入 leader 后,follower 是被动的去 leader 进行同步的!producer 采纳 push 模式将数据公布到 broker,每条音讯追加到分区中,程序写入磁盘,所以保障 同一分区 内的数据是有序的!写入示意图如下:
下面说到数据会写入到不同的分区,那 kafka 为什么要做分区呢?置信大家应该也能猜到,分区的次要目标是:
1、不便扩大。因为一个 topic 能够有多个 partition,所以咱们能够通过扩大机器去轻松的应答日益增长的数据量。
2、进步并发。以 partition 为读写单位,能够多个消费者同时生产数据,进步了音讯的解决效率。
相熟负载平衡的敌人应该晓得,当咱们向某个服务器发送申请的时候,服务端可能会对申请做一个负载,将流量散发到不同的服务器,那在 kafka 中,如果某个 topic 有多个 partition,producer 又怎么晓得该将数据发往哪个 partition 呢?
kafka 中有几个准则:
1、partition 在写入的时候能够指定须要写入的 partition,如果有指定,则写入对应的 partition。
2、如果没有指定 partition,然而设置了数据的 key,则会依据 key 的值 hash 出一个 partition。
3、如果既没指定 partition,又没有设置 key,则会轮询选出一个 partition。
保障音讯不失落是一个音讯队列中间件的根本保障,那 producer 在向 kafka 写入音讯的时候,怎么保障音讯不失落呢?其实下面的写入流程图中有形容进去,那就是通过 ACK 应答机制!在生产者向队列写入数据的时候能够设置参数来确定是否确认 kafka 接管到数据,这个参数可设置的值为0、1、all。
0 代表 producer 往集群发送数据不须要等到集群的返回,不确保音讯发送胜利。安全性最低然而效率最高。
1 代表 producer 往集群发送数据只有 leader 应答就能够发送下一条,只确保 leader 发送胜利。
all 代表 producer 往集群发送数据须要所有的 follower 都实现从 leader 的同步才会发送下一条,确保 leader 发送胜利和所有的正本都实现备份。安全性最高,然而效率最低。
最初要留神的是,如果往不存在的 topic 写数据,能不能写入胜利呢?kafka 会主动创立 topic,分区和正本的数量依据默认配置都是 1。
保留数据
Producer 将数据写入 kafka 后,集群就须要对数据进行保留了!kafka 将数据保留在磁盘,可能在咱们的个别的认知里,写入磁盘是比拟耗时的操作,不适宜这种高并发的组件。Kafka 初始会独自开拓一块磁盘空间,程序写入数据(效率比随机写入高)。
Partition 构造
后面说过了每个 topic 都能够分为一个或多个 partition,如果你感觉 topic 比拟形象,那 partition 就是比拟具体的货色了!Partition 在服务器上的表现形式就是一个一个的文件夹,每个 partition 的文件夹上面会有多组 segment 文件,每组 segment 文件又蕴含.index 文件、.log 文件、.timeindex 文件(晚期版本中没有)三个文件,log 文件就理论是存储 message 的中央,而 index 和 timeindex 文件为索引文件,用于检索音讯。
如上图,这个 partition 有三组 segment 文件,每个 log 文件的大小是一样的,然而存储的 message 数量是不肯定相等的(每条的 message 大小不统一)。文件的命名是以该 segment 最小 offset 来命名的,如 000.index 存储 offset 为 0~368795 的音讯,kafka 就是利用分段 + 索引的形式来解决查找效率的问题。
Message 构造
下面说到 log 文件就理论是存储 message 的中央,咱们在 producer 往 kafka 写入的也是一条一条的 message,那存储在 log 中的 message 是什么样子的呢?音讯次要蕴含音讯体、音讯大小、offset、压缩类型……等等!咱们重点须要晓得的是上面三个:
1、offset:offset 是一个占 8byte 的有序 id 号,它能够惟一确定每条音讯在 parition 内的地位!
2、音讯大小:音讯大小占用 4byte,用于形容音讯的大小。
3、音讯体:音讯体寄存的是理论的音讯数据(被压缩过),占用的空间依据具体的音讯而不一样。
存储策略
无论音讯是否被生产,kafka 都会保留所有的音讯。那对于旧数据有什么删除策略呢?
1、基于工夫,默认配置是 168 小时(7 天)。
2、基于大小,默认配置是 1073741824。
须要留神的是,kafka 读取特定音讯的工夫复杂度是 O(1),所以这里删除过期的文件并不会进步 kafka 的性能!
生产数据
音讯存储在 log 文件后,消费者就能够进行生产了。与生产音讯雷同的是,消费者在拉取音讯的时候也是 找 leader去拉取。
多个消费者能够组成一个消费者组(consumer group),每个消费者组都有一个组 id!同一个生产组者的消费者能够生产同一 topic 下不同分区的数据,然而不会组内多个消费者生产同一分区的数据!!!是不是有点绕。咱们看下图:
图示是消费者组内的消费者小于 partition 数量的状况,所以会呈现某个消费者生产多个 partition 数据的状况,生产的速度也就不迭只解决一个 partition 的消费者的处理速度!如果是消费者组的消费者多于 partition 的数量,那会不会呈现多个消费者生产同一个 partition 的数据呢?下面曾经提到过不会呈现这种状况!多进去的消费者不生产任何 partition 的数据。所以在理论的利用中,倡议 消费者组的 consumer 的数量与 partition 的数量统一!
在保留数据的大节外面,咱们聊到了 partition 划分为多组 segment,每个 segment 又蕴含.log、.index、.timeindex 文件,寄存的每条 message 蕴含 offset、音讯大小、音讯体……咱们屡次提到 segment 和 offset,查找音讯的时候是怎么利用 segment+offset 配合查找的呢?如果当初须要查找一个 offset 为 368801 的 message 是什么样的过程呢?咱们先看看上面的图:
1、先找到 offset 的 368801message 所在的 segment 文件(利用二分法查找),这里找到的就是在第二个 segment 文件。
2、关上找到的 segment 中的.index 文件(也就是 368796.index 文件,该文件起始偏移量为 368796+1,咱们要查找的 offset 为 368801 的 message 在该 index 内的偏移量为 368796+5=368801,所以这里要查找的 绝对 offset为 5)。因为该文件采纳的是稠密索引的形式存储着绝对 offset 及对应 message 物理偏移量的关系,所以间接找绝对 offset 为 5 的索引找不到,这里同样利用二分法查找绝对 offset 小于或者等于指定的绝对 offset 的索引条目中最大的那个绝对 offset,所以找到的是绝对 offset 为 4 的这个索引。
3、依据找到的绝对 offset 为 4 的索引确定 message 存储的物理偏移地位为 256。关上数据文件,从地位为 256 的那个中央开始程序扫描直到找到 offset 为 368801 的那条 Message。
这套机制是建设在 offset 为有序的根底上,利用 segment+ 有序 offset+稠密索引 + 二分查找 + 程序查找 等多种手段来高效的查找数据!至此,消费者就能拿到须要解决的数据进行解决了。
那每个消费者又是怎么记录本人生产的地位呢?在晚期的版本中,消费者将生产到的 offset 保护 zookeeper 中,consumer 每距离一段时间上报一次,这里容易导致反复生产,且性能不好!在新的版本中消费者生产到的 offset 曾经间接保护在 kafk 集群的__consumer_offsets 这个 topic 中!
起源:17coding 技术博客
近期热文举荐:
1.600+ 道 Java 面试题及答案整顿(2021 最新版)
2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!
3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!