@

前言:为什么需要Kafka

举个例子:麦当劳点餐时,当我们选择外带的时候,餐厅制作好餐之后会放在一个取餐台,而且取餐台是按照不同的取餐码尾号分开放置的,按照餐品的产出顺序进行放置的。这时候我们可以在我们空闲的时候去取餐,而餐厅也不用等待我们拿完餐再生产。而这个取餐台就像一个消息队列。我们现在想想如果没有这个取餐台会发生什么?餐厅不断需要顾客及时取走,不然会严重影响到餐厅的出餐和订单处理。那消费者也要关注取餐的信息,自己的时间安排自由度就下降了。so,取餐台这个中间缓冲的对象就可以接触消费者和餐厅的强绑定关系,让餐厅和消费者都可以自由化做各自的事情。

Kafka所扮演的角色就是类似当前取餐台的功能,当然起作用不仅仅是缓冲,在接下来的内容中一起揭开kafka的面纱,一窥其工作机理和设计思想。

1.初识kafka

我们先来看看Kafka是怎么定义的?

kafka是一个分布式的基于发布/订阅模式的消息队列。

那啥是消息队列啊。如我们开篇讲到的那个取餐台就是一个消息队列。就是在消息传输过程中保存消息的容器。其本质就是:

消息发送者(我们称之为生产者,多形象)——>MQ(message queue消息队列,消息保存的容器)——>消息接受者(消息的消费者)

消息队列就是可以接受生产者发送的消息并保存起来,队列Queue,按照消息接受的顺序存储,然后等待消费者进行消费消息。消息队列的作用就是保存消息并转发消息。

1.1 消息队列的好处:

1)解耦

允许我们独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

2)可恢复性

系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

3)缓冲

有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。

4)灵活性 & 峰值处理能力 (削峰)

在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。比如:618,双十一等活动,00:00 大量的手速点击访问,如果没有消息队列作为缓冲,所有请求都打到Redis,mysql等服务器,他们也扛不住啊。

5)异步通信

很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

1.2 消息队列的两种模式

(1)点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除)

消息生产者生产消息发送到Queue中,然后消息消费者从Queue中取出并且消费消息。

消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。

2)发布/订阅模式(一对多,消费者消费数据之后不会清除消息)

消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。

发布-订阅(Publish/Subscribe)模式(又被称为观察者模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

我们看看传统的MQ有什么问题?

没有消息队列我们怎么做?

假设现在我们的应用程序需要往别处发送监控信息,可以直接在应用程序和另一个可以在仪表盘上显示度量指标的应用程序之间建立连接 然后通过这个连接推送度量指标,

我们可以这样做:

这是刚接触监控系统时简单问题的应对方案。过了不久,你需要分析更长时间片段的度量指标,而此时的仪表盘程序满足不了需求,于是,你启动了一个新的服务来接收度盘指标。该服务把度量指标保存起来,然后进行分析。与此同时,你修改了原来的应用程序, 把度量指标同时发送到两个仪表盘系统上。

现在,你又多了3个可以生成度量指标 应用 程序,它们都与这两个服务直接相连。而你的同事认为最好可以对这些服务进行轮询以便 获得告警功能,于是你为每一个应用程序增加了一个服务器,用于提供度量指标。再过一阵子,有更多的应用程序出于各自的目的,都从这些服务器获取度主指标。这时的架构看起来就像下图所示一样,节点间的连接一团糟。

传统MQ怎么做?

我们创建一个基于发布订阅的消息队列, 用于接收来自其他应用程序的度量指标,井为其他系统提供了一个查询服务器。

这时候一切都看起来这么清爽和简单,但是当我们和度量指标进行了一轮“艰苦奋战”之后,其他同事也要和各自的任务进行battle。另一个同事也正在跟日志消息奋战。还有另一个同事正在跟踪网站用户的行为,为负责机器学习开发的同事提供信息 ,同时为管理团队生成报告。你和同事们使用相同的方式创建这些系统,解辑信息的发布者和订阅者。然后发现世界好像又不美好了?看图:

由于不同的业务任务,我们产生了多个消息队列进行各自业务的处理,但是这里有很多重复的地方。而且由于不同的业务模块,开发人员需要为各自的业务指标任务维护一套内容,而且之后或许还有其他的业务需要构建新的消息队列进行处理,资源浪费且每天维护这些内容,出现BUG的排查等等都会带来极大的不便性。但是又因为传统消息队列中的一个消息只能被消费一次,这时候我们就想,如果消息队列可以对于不同的业务的消费者看做不同的消费者,他们都可以消费消息队列中的消息就可以共用这些消息系统了。岂不是美滋滋,即便是后边需要增加业务,也不用独立的使用新的消息队列,世界又变得美好万分。

这时候,Kafka就”闪亮登场“了

Kafka的数据按照一定的顺序持久化保存,可以按需读取,通过对于不同的群组的消费者重新数据的消费状态实现多消费者共同消费消息等。具体的数据一致性保证以及生产者消费者写入和读取数据是怎么进行的,在后边的内容会与展开讲述。

2. Kafka基本架构

2.1 前备知识

1.消息和批次

Kafka 的数据单元被称为消息。消息由字节数组组成,所以对于Kafka来说,消息里的数据没有特别的格式或含义。消息可以有一个可选的元数据,也就是键。键也是一个字节数组,与消息一样,对于Kafka来说也没有特殊的含义。消息以一种可控的方式写入不同的分区时,会用到键。最简单的例子就是为键生成一个一致性散列值,然后使用散列值对主题分区数进行取模,为消息选取分区。

\[patitionnum = mod(hash(key) , partitions)
\]

这样可以保证具有相同键的消息总是被写到相同的分区上。为了提高效率,消息被分批次写入 Kafka 。批次就是一组消息,这些消息属于同一个主题和分区。如果每 个消息都单独在网络传输,会导致大量的网络开销,把消息分成批次传输可以减少网络开销。不过,这要在时间延迟和吞吐量之间作出权衡:批次越大,单位时间内处理的消息就越多,单个消息的传输时间就越长。批次数据会被压缩,这样可以提升数据的传输和存储能力,但要做更多的计算处理。

2.消息模式

对于Kafka而言,消息的底层是一组字节数组,是我们难以辨识的内容。为了更好的理解这些消息,就有开发者提出用额外的一种结构来定义消息内容。比如常见的JSON和XML。这些结构不仅易用,且可读性好。Kafka一般采用Avro。Avro提供了一种紧凑的序列化格式,其模式和消息体是分开的。另外Avro也是由Doug Cutting创建的哦。因为Avro的一些特性,很适合Kafka这样的消息队列。消除了消息读写操作之间的耦合性。

如果读写操作紧密地耦合在一起,消息订阅者需要升级应用程序才能同时处理新旧两种数据格式。在消息订阅者升级了之后,消息发布者才能跟着升级,以便使用新的数据格式。新的 应用程序如果需要使用数据,就要与消息发布者发生耦合,导致开发者需要做很多繁杂操作。

在对于当前架构进行拆分看待前,我们先来关注一些Kafka独到的机制和单元:

图片引用来自知乎老刘

2.2 架构分析

1)Producer :消息生产者,就是向kafka broker发消息的客户端

生产者创建消息。一般情况下,一个消息会被发布到一个特定的主题上。生产者在默认情况下把消息均衡地分布到主题的所有分区上,而并不关心特定消息会被写到哪个分区。不过,在某些情况下,生产 者会把消息直接写到指定的分区。这通常是通过消息键和分区器来实现的,分区器为键生 成一个散列值,并将其映射到指定的分区上。这样可以保证包含同一个键的消息会被写到 同一个分区上。生产者也可以使用自定义的分区器,根据不同的业务规则将消息映射到分区。

生产者具体的一些消息写入细节会在下一个文章进行讲述。毕竟一个篇幅如果太长,也不能做到详尽,也怕小伙伴没有时间看完。

2)Consumer :消息消费者,向kafka broker取消息的客户端

消费者读取消息。消费者订阅一个或多个主题,并按照消息生成的顺序读取它们。消费者通过检查消息的偏移量来区 分已经读取过的消息。 偏移量是另一种元数据,它是一个不断递增的整数值,在创建消息时, Kafka 会把它添加到消息里。在给定的分区里,每个悄息的偏移量都是唯一的。消费者把每个分区最后读取的悄息偏移量保存在 Zookeeper或Kafka 上,如果悄费者关闭或重启,它的读取状态不会丢失。

消费者是消费者群组的一部分,也就是说,会有一个或多个消费者共同读取一个主题。群组保证每个分区只能被一个消费者使用 。

有3消费者同时读取1个主题。其中的两个消费者各自读取一个分区,另外一个消费者读取其他两个分区。消费者与分区之间的映射通常被称为消费者对分区的所有权关系。

通过这种方式,消费者可以消费包含大量消息的主题。而且,如果一个消费者失效,群组里的其他消费者可以接管失效消费者的工作。

3)Consumer Group (CG):消费者组,由多个consumer组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。

消费者组,组中有多个消费者。

​ 组中消费者的个数最好 = topic分区数

​ 如果消费者组中消费者个数>topic分区数,此时有个别消费者没有分区可以消费

​ 如果消费者组中消费者个数<topic分区数,此时有个别消费者需要消费多个分区的数据

**4)Broker **:一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic。

broker 接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。 broker 为消费者提供服务,对读取分区的请求作出响应,返 回已经提交到磁盘上的消息。根据特定的硬件及其性能特征,单个 broker 可以轻松处理数千个分区以及每秒百万级的消息量。

broker 是集群的组成部分。每个集群都有一个 broker 同时充当了集群控制器的角色Collector(自动从集群的活跃成员中选举出来)。控制器负责管理工作,包括将分区分配给 broker 和监控 broker。在集群中, 一个分区从属于一个 broker, 该broker 被称为分区的首领。一个分区可以分配给多个 broke ,这个时候会发生分区复制。这种复制机制为分区提供 了消息冗余,如果有一个 broker 失效,其他 broker 可以接管领导权。不过,相关的消费者和生产者都要重新连接到新的首领。

分区复制

5)Topic :可以理解为一个队列,生产者和消费者面向的都是一个topic

6)Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列;

7)Replica:副本,为保证集群中的某个节点发生故障时,该节点上的partition数据不丢失,且kafka仍然能够继续工作,kafka提供了副本机制,一个topic的每个分区都有若干个副本,一个leader和若干个follower

8)leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是leader。

9)follower:每个分区多个副本中的“从”,实时从leader中同步数据,保持和leader数据的同步。leader发生故障时,某个follower会成为新的leader。

2.3Kafka 特点

1.多个生产者

Kafka 可以无缝地支持多个生产者,不管客户端在使用单个主题还是多个主题。所以它很适合用来从多个前端系统收集数据,并以统 的格式对外提供数据。

2.多个消费者

Kafka 也支持多个消费者从一个单独的消息流上读取数据,而且消费者之间互不影响。这与其他队列系统不同,其他队列系统的消息一旦被一个客户端读 取,其他客户端就无法再读取它。另外,多个消费者可以组成一个群组,它们共享一个消息流,并保证整个群组对每个给定的消息只处理一次。

3.基于磁盘的数据存储

Kafka 的数据 保留特性。消息被提交到磁盘,根据设置的保留规则进行保存。每个主题可以设置单独的保留规则,以便满足不同消费者的需求,各个主题可以保留不同数量的消息。消费者可能会因为处理速度慢或突发的流量高峰导致无陆及时读取消息,而持久化数据可以保证数据 不会丢失。消费者可以在进行应用程序维护时离线一小段时间,而无需担心消息丢失或堵塞在生产者端。消费者可以被关闭,但消息会继续保留在 Kafka 里。消费者可以从上次中 断的地方继续处理消息。

4.伸缩性

为了能够轻松处理大量数据, Kafka 一开始就被设计成一个具有灵活伸缩性的系统。用户在开发阶段可以先使用单个 broker ,再扩展到包含3个 broker 的小型开发集群,然后随着数据量不断增长,部署到生产环境的集群可能包含上百个 broker 。对在线集群进行扩展丝毫不影响整体系统的可用性。也就是说,一个包含多个 broker 的集群,即使个别Broker失效,仍然可以持续地为客户提供服务。

5.高性能

前面提到的所有特性,让 Kafka 成为了一个高性能的发布与订阅消息系统。通过横向扩展生产者、消费者和 broker, Kafka 可以轻松处理巨大的消息流。在处理大量数据的同时, 它还能保证亚秒级的消息延迟。

3 总结

我们通过麦当劳的例子开始进入消息队列,并从点对点业务到发布订阅的消息队列以及他们存在的弊端引入Kafka。我们知道了Kafka是一个流平台,将数据看做是持续变化和不断增长的流,可以通过发布和订阅数据流,并把他们保存起来进行处理的数据系统。我们称之为数据系统是因为kafka有别于消息系统的分布式部署方式,可以自由伸缩、处理企业内所有的应用程序。kafka不仅仅是传递消息,其还可以数据的可复制、持久化,其保留时长由我们来进行设置。

也了解了Kafka的基础架构,Kafka的组成以及自个的作用和简单做了什么事情。对于Kafka大致有一个比较简单的了解,在下篇内容中我们将走入Kafka内部到底是做了什么。以及生产者消费者如何写入和消费数据的,如何在写入和消费的时候保证的数据一致性。解决节点失效以及内部的选举机制。

我们要仰望星空,亦需脚踏实地。怕什么真理无穷,进一寸有一寸的欢喜。我是清风,希望这篇文章对你有帮助。如有不准确之处,还请评论区留言讨论。

女朋友看了也懂的Kafka(上篇)的更多相关文章

  1. 女朋友看了也懂的Kafka(下篇)

    前言: 在上篇中我们了解了Kafka是什么,为什么需要Kafka,以及Kafka的基本架构和各自的作用是什么,这篇文章中我们将从kafka内部每一个组成部分去看kafka 是如何保证数据的可靠性以及工 ...

  2. 深度剖析HashMap的数据存储实现原理(看完必懂篇)

    深度剖析HashMap的数据存储实现原理(看完必懂篇) 具体的原理分析可以参考一下两篇文章,有透彻的分析! 参考资料: 1. https://www.jianshu.com/p/17177c12f84 ...

  3. [转帖]Linux shell中2>&1的含义解释 (全网最全,看完就懂)

    Linux shell中2>&1的含义解释 (全网最全,看完就懂) https://blog.csdn.net/zhaominpro/article/details/82630528   ...

  4. 2018前端面试总结,看完弄懂,工资少说加3K | 掘金技术征文

    2018前端面试总结,看完弄懂,工资少说加3K | 掘金技术征文:https://juejin.im/post/5b94d8965188255c5a0cdc02

  5. python编程系列---白痴女朋友(我没有女朋友!)看了都能懂的TCP/IP协议介绍

    前言 早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Microsoft都有各自的网络协议,互不兼容:为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套全球通用的协议,为 ...

  6. java回调函数,看完就懂

    java回调函数在网上了看了些例子,比较绕,不够清晰,自己写的一个例子比较通俗,java回调其实很简单. 举个例子我是类B,我有个方法叫b(),现在我要调用类A中的方法a(),写个代码就是: publ ...

  7. 看完肯定懂的 Java 字符串常量池指南

    字符串问题可谓是 Java 中经久不衰的问题,尤其是字符串常量池经常作为面试题出现.可即便是看似简单而又经常被提起的问题,还是有好多同学一知半解,看上去懂了,仔细分析起来却又发现不太明白. 背景说明 ...

  8. 单例模式(Singleton)看了就懂

    单例,故名思议,一个只能创建一个实例的类. 单例被广泛应用于Spring的bean(默认).线程池.数据库连接池.缓存,还有其他一些无状态的类如servlet. 一个没必要多例的类实现了单例可以节约空 ...

  9. 一看你就懂,超详细java中的ClassLoader详解

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 ClassLoader翻译过来就是类加载器,普通的Java开发者其实用到的不多,但对于某些框架开发者来说却非常常见.理解ClassL ...

随机推荐

  1. 1076 Forwards on Weibo

    Weibo is known as the Chinese version of Twitter. One user on Weibo may have many followers, and may ...

  2. 织梦DedeCMS自定义表单限制IP24小时只能提交多少次

    方法1.打开plus/diy.php,找到一下代码, if(!is_array($diyform)) { showmsg('自定义表单不存在', '-1'); exit(); } 然后再在以下代码后面 ...

  3. Python 巡检接入钉钉机器人

    前段时间,为了快速实现巡检服务器设备的健康状态,我简单的写了一个巡检工具,该工具已经可以满足我的大部分需求了,不过,每次都要自己手动去点击巡检才能知道今天设备的状态,由于每天巡检严重影响我学习逆向技术 ...

  4. 文档翻译第002篇:Process Monitor帮助文档(Part 2)

    [筛选与高亮显示] Process Monitor提供了一些方式来配置筛选器和高亮显示.         筛选器的包含与排除 您可以在筛选器中指定事件的属性,这样就可以令Process Monitor ...

  5. 一枚Android "短信小偷" 病毒的分析

    一.样本简介 样本来自于吾爱破解论坛链接地址为http://www.52pojie.cn/thread-410238-1-1.html,样本不是很复杂有空就分析了一下.Android病毒样本还是很有意 ...

  6. Python小程序 -- 人民币小写转大写辅助工具

    大家应该都知道,银行打印账单有时候会跟上人民币的阿拉伯数字以及人民币汉字大写写法,转换的过程中有一定的逻辑难度,较为麻烦,所以笔者心血来潮,花了点时间简单实现了一下这一转换过程,以供初学者参考. 输入 ...

  7. Win64 驱动内核编程-28.枚举消息钩子

    枚举消息钩子 简单粘贴点百度的解释,科普下消息钩子: 钩子是WINDOWS中消息处理机制的一个要点,通过安装各种钩子,应用程序能够设置相应的子例程来监视系统里的消息传递以及在这些消息到达目标窗口程序之 ...

  8. 学习Canvas绘图与动画基础 绘制多条路径(四)

    1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="U ...

  9. 【vue-03】组件化开发 component

    vue组件化思想 组件化是vue的一个重要思想 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构建我们的应用. 任何的应用都会被抽象成一颗组件树. 注册组件 组件的使用分成三个步骤:创建 ...

  10. Ubuntu执行命令时,不sudo提示权限不足,sudo提示找不到该命令

    问题:Ubuntu执行命令时,不sudo提示权限不足,sudo提示找不到该命令 补充描述:尝试将命令所在路径添加到/etc/profile中(所有用户环境变量),结果sudo -i切换到root用户后 ...