关于消息队列:十二张图踹开消息队列的大门

42次阅读

共计 3352 个字符,预计需要花费 9 分钟才能阅读完成。

音讯队列つ退场

大家好,我是老三,是一个电商公司的程序员,负责订单零碎的开发。

掉了不少头发之后,我实现了用户订单领取的开发。

订单领取的业务是这样的。用户领取实现之后,我须要更新订单状态,这一部分是在本零碎实现的。接下来,我要调用库存零碎,减库存,好了,剩下的就是库存零碎的事件了。

开发、联调、测试、上线,我的小日子变得安闲起来,每天就是在群里吹牛打屁。

可是没过两天,产品妹子,找过去了,她说,她想加个性能,用户实现订单领取当前,要减少用户的积分。

没问题,so easy,噼里啪啦,我两天就做完了,无非是调用一下会员零碎。

这天,正和沙雕群友斗图的时候,产品妹子过去,他说要接入音讯零碎,好,搞!

又过两天,她说要增加营销零碎,行吧,干!

又过两天,她说要搞举荐零碎,嗯……,来吧!

又过两天……

于是零碎就变成了这个样子:

就这样,我过上了暗无天日的日子,我要保护和若干个零碎的对接,每次他们公布新版本,我都要跟着值班。

我要迭代,也要改和几个零碎的对接代码。

周一,营销零碎;

周二,库存零碎;

……

这天,眼圈发黑的我正在和上游服务撕巴的时候,忽然忍不住两腿战战,她来了,产品 (女)(王)来了——她是我不能回绝的女人。

软弱的眼泪流了满面,我的猿生一片灰暗……

没想到,代救星呈现了,我的好敌人傲天过去了,拿鼻孔看着我。

“你个 Loser,竟不晓得用音讯队列,怪不得天天被人欺侮,哼!”

一语惊醒梦中人,为什么不必音讯队列啊?

于是我引入音讯队列,对系统进行了重构。

这下好了,我只管 更新订单状态,剩下的丢给音讯队列,你们这些上游本人去音讯队列生产音讯就好了,别来缠着我了。

……

引入音讯队列之后,又是一个安逸的下午。

我没有在群聊里扯扯,因为我退群了。

前几天,我受到了前所未有的挫伤——

我在群里讥嘲一个老哥,技术真菜,连音讯队列都不会!

老哥反手就收回他和女朋友的合照,“独身狗,技术好又怎么样,连个女朋友都没有!”

我霎时 san 值狂掉!

“程序员独身,不算独身……new 个对象的事,能算独身么?”接连着便是什么难懂的话,什么“没有妹子”,什么“哲学”之类,引得众人都哄笑起来,群里充斥了快活的空气。

于是,这个下午我盯着空洞无物的需要单发愣,公司真的没有妹子么?……

好了,简短的前奏完结了,接下来该进入注释了😂。

音讯队列つ用处

在下面的前言中,咱们曾经理解了音讯队列最重要的一个用处:

  • 解耦

通过音讯队列,升高零碎间的耦合,防止过多的调用。

就如同公司的行政小姐姐要告诉一件事件,她通常会是在群里发一个布告,而后咱们扣 1 就行了。要是一个个告诉,她要告诉几十上百次。

  • 异步

还是下面咱们提到的订单领取,领取之后,咱们要扣减库存、减少积分、发送音讯等等,这样一来这个链路就长了,链路一长,响应工夫就变长了。引入音讯队列,除了 更新订单状态 ,其它的都能够 异步 去做,这样一来就来,就能更快地响应咱们的上游。

为什么不必多线程之类的形式做异步呢?——

嗨,只用多线程做异步,不是还得写代码去调那一堆上游吗,所以这又回到理解耦这个问题上。

  • 削峰

音讯队列同样能够用来削峰。

用一个比喻,一条河流,如果它的上游能包容的水量是无限的,为了避免洪水冲垮堤坝,咱们应该怎么办呢?

咱们能够在上游建筑一个水库,洪峰来的时候,咱们先把水给蓄起来,闸口里只放出上游能接受地住的水量。

放在咱们的零碎,也是一个情理。比方秒杀零碎,平时流量很低,然而要做秒杀流动,秒杀的时候流量疯狂怼进来,你的服务器,RedisMySQL各自的承受能力都不一样,间接全副流量照单全收必定有问题啊,重大点可能间接打挂了。

所以一样,咱们能够把申请放到队列外面,只放出咱们上游服务能解决的流量,这样就能抗住短时间的大流量了。

除了这三大用处之外,还能够利用队列自身的程序性,来满足音讯必须按程序投递的场景;利用队列 + 定时工作来实现音讯的延时生产 ……

音讯队列つ实质

过气老北鼻马老师有三招——

音讯队列外围有三板斧:生产

生产者先将音讯投递一个叫做「队列」的容器中,而后再从这个容器中取出音讯,最初再转发给消费者[1]。

下面这个图便是音讯队列最原始的模型,它蕴含了音讯队列中的一两个关键词 音讯 和队列 队列

  1. 音讯:就是要传输的数据,能够是最简略的文本字符串,也能够是自定义的简单格局。
  2. 队列:大家应该再相熟不过了,是一种先进先出数据结构。它是寄存音讯的容器,音讯从队尾入队,从队头出队,入队即发消息的过程,出队即收音讯的过程。

所以音讯队列的实质就是 把要传输的数据放在队列中。

围绕着这个实质:

  • 把数据放到音讯队列的角色就是 生产者
  • 把数据从队列中取出的就是 消费者

音讯队列つ模型

[1]咱们下面曾经理解了音讯队列模型的实质,随着利用场景的变动,音讯队列的模型逐步产生了一些演进。

就如同咱们的文字通信,最开始单对单地发消息,起初能够群发,再起初,能够拉一个群聊。

  • 队列模型

最后的音讯队列就是上一节讲的原始模型,它是一个严格意义上的队列(Queue)。音讯依照什么程序写进去,就依照什么程序读出来。不过,队列没有“读”这个操作,读就是出队,从队头中“删除”这个音讯。

如果有多个生产者往同一个队列外面发送音讯,这个队列中能够生产到的音讯,就是这些生产者生产的所有音讯的合集。音讯的程序就是这些生产者发送音讯的天然程序。

如果有多个消费者接管同一个队列的音讯,这些消费者之间实际上是竞争的关系,每个消费者只能收到队列中的一部分音讯,也就是说任何一条音讯只能被其中的一个消费者收到。

  • 公布 – 订阅模型

如果须要将一份音讯数据分发给多个消费者,并且每个消费者都要求收到全量的音讯。很显然,队列模型无奈满足这个需要。

一个可行的计划是:为每个消费者创立一个独自的队列,让生产者发送多份。这种做法比拟笨,而且同一份数据会被复制多份,也很节约空间。

为了解决这个问题,就演化出了另外一种音讯模型:公布 - 订阅模型。

在公布 – 订阅模型中,音讯的发送方称为发布者(Publisher),音讯的接管方称为订阅者(Subscriber),服务端寄存音讯的容器称为主题(Topic)。发布者将音讯发送到主题中,订阅者在接管音讯之前须要先“订阅主题”。“订阅”在这里既是一个动作,同时还能够认为是主题在生产时的一个逻辑正本,每份订阅中,订阅者都能够接管到主题的所有音讯。

认真比照下它和“队列模式”的异同:生产者就是发布者,队列就是主题,消费者就是订阅者,无本质区别。惟一的不同点在于:一份音讯数据是否能够被屡次生产。

音讯队列つ代价

天下没有白吃的午餐——这句话放在零碎设计中同样实用。引入了音讯队列,解决了一些问题,但同时也减少了零碎的复杂性和保护老本。[5]

  • 高可用

后面说,咱们引入了音讯队列,升高了零碎间的耦合,然而,咱们对音讯队列的依赖也变重了,想想,要是音讯队列挂了,那咱们上游就全凉了。

所以,咱们音讯队列的部署必须保障高可用,至多是 主 / 从 ,个别都得 集群 / 分布式

  • 音讯失落问题

咱们将数据写到音讯队列上,上游服务没来得及取音讯队列的数据,忽然挂了。如果没有做任何的措施,咱们的数据就丢了

那可怎么办呢?

音讯队列中的数据得想方法存在别的中央,这样才尽可能减少数据的失落。

问题又来了,存在哪呢?

  • 磁盘?
  • 数据库?
  • Redis?
  • 分布式文件系统?

同步存储还是异步存储?

  • 反复生产问题

要是咱们网络提早或者什么起因,导致上游反复生产怎么办?

咱们这个问题是在音讯队列解决?还是在上游服务解决?

还有其它的程序音讯等等问题。

这些问题都是选型时候须要充分考虑的。

音讯队列つ抉择

目前在市面上比拟支流的次要有四大消息中间件:Kafka、ActiveMQ、RabbitMQ、RocketMQ

它们的比照我整顿了一张图:

音讯队列つ终焉

好了,到这咱们就理解了音讯队列的一些根底的常识。

门外汉,这个门,你入了吗?我反正是在外面打滚了。

“ 简略的事件反复做,反复的事件认真做,认真的事件有创造性地做!”——

我是三分恶,一个能文能武的全栈开发。

点赞 关注 不迷路,咱们下期见!


<big>参考:</big>

[1].《吃透 MQ 系列》外围根底全在这里了

[2].《进大厂系列》系列 - 音讯队列根底

[3]. 知乎问答:音讯队列怎么能艰深点解释?

[4]. 零碎学习音讯队列分享(四)音讯模型:主题和队列有什么区别?

[5]. 什么是音讯队列?

正文完
 0