由浅到深学习kafka(一):什么是kafka
kafka作为一个十分流行的大数据技术,它的流行不光是好用那么简单,作为一名大数据技术人员,仅会简单的使用与开发,有点“out”了,于是我在极客时间中找到了一份不错的资料,帮助我由浅到深的学习kafka,我将学习的笔记记录到博客中,用作参考
Kafka是什么?
用一句话概括它:Apache Kafka是一款开源的消息引擎系统
看到“消息引擎”这个词,可能大家会有陌生,那么“消息队列”,“消息中间件”想必有所耳闻
但从字面上来看,“消息队列”仿佛kafka是利用队列的方式构建的,会产生误解
“消息中间件”又过于夸张,不知道“中间件”到底是什么,这个中间件起到了什么作用呢?
我更倾向与叫它“消息引擎系统”
想kafka这一类的系统,在国外有专属的名字叫:Messaging System,国内将它翻译为消息系统,我个人认为并不是很恰当,因为它片面强调了消息主体的作用,而忽视了这类系统引以为傲的消息传递属性,就像引擎一样,具备某种能量转换传输的能力,所以我觉得翻译成消息引擎反倒更加贴切。
消息引擎系统是什么?
维基百科将其定义为:消息引擎是一组规范,企业利用这组规范在不同系统之间传递语义准确的消息,实现松耦合的异步式数据传递。
官方的定义比较高端哈,我们来个通俗易懂的版本:系统A发送消息给消息引擎系统,系统B从消息引擎系统中读取系统A发送的消息
最基础的消息引擎系统就是做这个的,但无论是哪种定义,它们都有两个相同点:
- 消息引擎传输的是消息
- 如何传输消息属于消息引擎设计机制的一部分
既然消息引擎是用于在不同系统之间传输消息的,那么如何设计待传输消息的格式是头等的大事
试问一条消息如何做到信息表达业务语义而无歧义,同时它还要能最大限度地提供可重用性以及通用性?
如果是你,你要如何设计你的消息编码格式?
一个比较容易想到的是使用已有的一些成熟解决方案,比如使用CSV、XML亦或是JSON;又或者你可能熟知国外大厂开源的一些序列化框架,比如Google的Protocol Buffer或Facebook的Avro,这些都是不错的选择
那么现在我告诉你Kafka的选择:它使用的是纯二进制的字节序列
当然消息还是结构化的,只是在使消息引擎传输的对象是消息;如何传输消息属于消息引擎设计机制的一部分。用之前都要将其转换成二进制的字节序列
消息设计出来之后还不够,消息引擎系统还要设定具体的传输协议,即我用什么方法把消息传输出去
常见的有两种方法:
- 点对点模型/消息队列模式:也叫消息队列模型。如果拿上面那个“通俗易懂版”的定义来说,那么系统A发送的消息只能被系统B接收,其他任何系统都不能读取A发送的消息。日常生活的例子比如电话客服就属于这种模型:同一个客户呼入电话只能被一位客服人员处理,第二个客服人员不能为该客户服务
- 发布/订阅模型:与上面不同的是,它有一个主题(Topic)的概念,你可以理解成逻辑语义相近的消息容器。该模型也有发送方和接收方,只不过提法不同。发送方也称为发布者(Publisher),接收方称为订阅者(Subscriber)。和点对点模型不同的是,这个模型可能存在多个发布者向相同的主题发送消息,而订阅者也可能存在多个,它们都能接收到相同主题的消息。生活中的报纸订阅就是一种典型的发布/订阅模型
Kafka同时支持这两种消息引擎模型!
提到消息引擎系统,你可能会问JMS和它是什么关系
JMS是Java Message Service,它也是支持上面这两种消息引擎模型的,严格来说它并非传输协议而仅仅是一组API罢了
不过可能是JMS太有名气以至于很多主流消息引擎系统都支持JMS规范,比如ActiveMQ、RabbitMQ、IBM的WebSphere MQ和Apache Kafka
当然Kafka并未完全遵照JMS规范,相反,它另辟蹊径,探索出了一条特有的道路
为什么要使用消息引擎系统?
在我们了解了消息引擎系统后,还有个重要的问题:为什么要使用消息引擎系统?
上面给了个通俗的定义:系统A将消息发送到消息引擎系统,消息B从消息引擎系统中读取系统A发送的消息
那么问题来了,为什么系统A不直接将消息发送到系统B,为什么中间隔着一个消息引擎系统呢?
答案就是 削峰填谷,这四个字简直比消息引擎本身还要有名气
所谓的“削峰填谷”就是指缓冲上下游瞬时突发流量,使其更平滑,特别是对于那种发送能力很强的上游系统,如果没有消息引擎的保护,“脆弱”的下游系统可能会直接被压垮导致全链路服务“雪崩”
但一旦有了消息引擎,它能够有效地对抗上游的流量冲击,真正做到将上游的“峰”填满到“谷”中,避免了流量的震荡
消息引擎系统的另一大好处在于发送方和接收方的松耦合,这也在一定程度上简化了应用的开发,减少了系统间不必要的交互
举个栗子:
回想一下极客时间是如何购买课程的:极客时间每门课程都有一个专门的订阅按钮,点击之后进入到付费页面
这个简单的流程中就可能包含多个子服务,比如点击订阅按钮会调用订单系统生成对应的订单,而处理该订单会依次调用下游的多个子系统服务 ,比如调用支付宝和微信支付的接口、查询你的登录信息、验证课程信息等
显然上游的订单操作比较简单,它的TPS要远高于处理订单的下游服务,因此如果上下游系统直接对接,势必会出现下游服务无法及时处理上游订单从而造成订单堆积的情形
特别是当出现类似于秒杀这样的业务时,上游订单流量会瞬时增加,可能出现的结果就是直接压跨下游子系统服务,解决此问题的一个常见做法是我们对上游系统进行限速,但这种做法对上游系统而言显然是不合理的,毕竟问题并不出现在它那里
所以更常见的办法是引入像Kafka这样的消息引擎系统来对抗这种上下游系统TPS的错配以及瞬时峰值流量
继续这个栗子:
当引入了Kafka之后,上游订单服务不再直接与下游子服务进行交互,当新订单生成后它仅仅是向Kafka Broker发送一条订单消息即可,类似地,下游的各个子服务订阅Kafka中的对应主题,并实时从该主题的各自分区(Partition)中获取到订单消息进行处理,从而实现了上游订单服务与下游订单处理服务的解耦
这样当出现秒杀业务时,Kafka能够将瞬时增加的订单流量全部以消息形式保存在对应的主题中,既不影响上游服务的TPS,同时也给下游子服务留出了充足的时间去消费它们
这就是Kafka这类消息引擎系统的最大意义所在
了解了kafka后,下篇文章将会介绍Kafka的常见概念和术语
我们下篇文章见~
亲,看完了点个赞吧!!!