消息队列 发明的初衷 是 降低下游的压力,让下游的服务按照自己的能力去消费。
但是这引发了另一个问题,如果下游服务的消费能力小于上游服务的生产能力,那么必然会造成消息积压,而且随着时间的累计会越积越多。
为了解决这个问题,不得不增加消费能力,但是又出现了一个问题,如果消费能力上去了,可以让队列里不积压消息了,那就说明消费能力不比生产能力差了,既然如此,为什么不直接让生产者调用消费者?
1
myd 2020-12-01 14:28:14 +08:00
如果没有队列,系统同时处理多个任务可能会崩溃。
另一方面,云服务器可以动态扩容,按需付费。 |
2
ruoxie 2020-12-01 14:29:02 +08:00 3
解耦算一个吧
|
3
Joker123456789 OP @myd 为什么会同时处理多个任务? 直接调用下游服务,让下游服务去处理啊? 下游服务也可以负载均衡,动态扩容啊。
|
4
Jooooooooo 2020-12-01 14:31:54 +08:00 1
消息队列不只有这一个功能
|
5
h82258652 2020-12-01 14:32:04 +08:00 6
假如上游的生产能力是动态的呢?例如某个时段高,其余时段低。
|
6
bnm965321 2020-12-01 14:33:30 +08:00 1
异步处理,然后对任务安全地消费泵机重启以后也能接着干
|
7
DoctorCat 2020-12-01 14:35:39 +08:00 6
解偶设计、异步任务、削峰
|
8
katsusan 2020-12-01 14:36:02 +08:00 2
最明显的一个原因就是上游的生产能力并不固定,当下游的消费能力不够需要扩容到扩容完成期间需要一个缓冲,消息队列正好提供了这个缓冲区。
|
9
KaynW 2020-12-01 14:36:23 +08:00
上游和下游的处理效率在每个时间段都可能不一样
|
10
Joker123456789 OP @h82258652 这个倒是个问题。 不过这个高,除了暴增,基本也不会有太大问题吧。 这个时间段保护了下游服务,但是上游服务一样遭受了大量的流量。
|
11
kuro1 2020-12-01 14:36:38 +08:00
削峰平谷
|
12
misaka19000 2020-12-01 14:37:36 +08:00
解耦
|
13
xx6412223 2020-12-01 14:38:04 +08:00 5
解耦,从开发过程到业务理念
企业的各种系统可能是几年间陆续上的,要考虑业务扩展性 对于 A 系统,完成一个业务流程后,为什么还要调用和我不相关的 B,C,D 系统,为什么要了解你的业务,你的系统宕机了我管不管? |
14
overthemoon 2020-12-01 14:38:43 +08:00
生产者消费过快,消费者消费过慢,会导致阻塞
|
15
shhch 2020-12-01 14:41:02 +08:00
服务解耦,异步处理都是;
防止瞬时峰值压垮服务;正常情况下处理能力是能够处理过来消息量的(你的服务至少要支撑起常态的访问量吧),但是一旦发生某些情况,比如什么活动啊,可能会有瞬发峰值产生,没有消息队列,可能会压垮某个服务;有了消息队列只是暂时消费服务没有处理完而已,不会被压垮;等消息量正常后,下游就可以处理完了; |
16
kiracyan 2020-12-01 14:42:10 +08:00
解耦 异步 削峰
|
17
securityCoding 2020-12-01 14:43:39 +08:00
1.流量削峰
2.同步转异步 3.系统解耦 |
18
a719031256 2020-12-01 14:44:03 +08:00
面试用
哪有那么多业务需要解耦,消息队列现在也就面试考考,实际真没太大用处,反而会让系统复杂 |
19
Joker123456789 OP |
20
killerv 2020-12-01 14:47:28 +08:00
一般消息队列处理的都是涉及三方、可延迟、服务质量不可控的行为,你无法保证调用第三方是否会出现超时、错误。
----------- 比如注册流程有个发短信的逻辑,但是短信服务出现了问题,如果走队列的话,一次调用失败,还可以继续尝试第二次第三次。但是如果没有队列,你难道要在当前请求中一直重试吗?这是个灾难。 |
21
jimmyismagic 2020-12-01 14:49:15 +08:00
消息队列能够增加吞吐量,就像程序员搬砖一样,如果每个人都从头搬到尾,效率低,而如果每个人接力,那么效率就快得多,而且不会来回堵塞道路,毕竟路的宽度是有限的
|
22
linxl 2020-12-01 14:52:48 +08:00
最近在下载视频, 如果不用消息队列, 那我买不起那么好的服务器
|
23
nnqijiu 2020-12-01 14:57:59 +08:00
本质就是作一个缓冲区
|
24
imn1 2020-12-01 15:20:09 +08:00
@nnqijiu +1
两点: 1. 核心处理能力总是有限的,就算很强,也是有限 2. 队列不一定是一维的,可以根据处理能力,把多个待处理任务放在队列同一个位置,这样也能高效发挥核心处理的能力 很多时候队列一维,只是受限于压入时只能逐个压入,可以做个“队列“的”队列”,把多个单一任务组成一组再压入队列 |
25
opengps 2020-12-01 15:24:34 +08:00 1
关键词:解耦
实现解耦时候,上下游各自开发各自的,只要用相同的规则去读 /写队列即可 |
26
snowwalf 2020-12-01 15:26:47 +08:00
削峰填谷,省钱
|
27
BigBunny 2020-12-01 15:37:40 +08:00 2
削峰,异步,解耦
|
28
walsh 2020-12-01 15:58:05 +08:00
不就是流水线机制吗,互联网喜欢重新发明新词
|
29
ggabc 2020-12-01 15:59:41 +08:00
其实,不用也不是不行,小系统不用他反而更简化
|
30
namelosw 2020-12-01 16:02:12 +08:00
> 但是这引发了另一个问题,如果下游服务的消费能力小于上游服务的生产能力,那么必然会造成消息积压,而且随着时间的累计会越积越多。
仅当削封填谷奏效的时候才行, 不过实际上绝大部分场景都很奏效. 积压的问题是下游的总计算能力先天就不足. 比如你的机器单位时间能做的计算是 10000, 处理一个 HTTP 请求的需要的计算是 1, 生成一个 report 需要的计算是 1000, 某些请求只是返回页面, 偶尔一些请求会生成 report. 假如生成 report 时候有一些高峰, 一旦需要生成 100 个 report 系统可能就会被拖死. 有 Queue 你可以规定同一时间比如只能生成 5 个 report. 现实世界中, 很多系统中如没有 Queue 的话, 几乎每个月都会发生这种点背的情况, 有 Queue 的话就直接避免了. |
31
kuaner 2020-12-01 16:09:27 +08:00
让杂乱无序的事情,变得有序
|
32
robinlovemaggie 2020-12-01 16:17:32 +08:00
想象一下摇·号于政·府的意义~
|
33
useben 2020-12-01 16:21:16 +08:00
解耦 异步 削峰 缓冲 协作开发
|
34
czzt1 2020-12-01 16:28:28 +08:00
削峰填谷
|
35
yolee599 2020-12-01 17:01:56 +08:00
一个是让你一天吃完十天量的饭,剩下的九天不吃;另一个是一天只吃一天的量,每天都吃。哪个比较好?
|
36
yangzzcc 2020-12-01 17:06:04 +08:00
不外乎几个作用, 解耦, 流量削峰, 异步...
|
37
HalloCQ 2020-12-01 17:09:40 +08:00
解耦、异步、削峰,消息队列的三大作用。面试不问的吗
|
38
northisland 2020-12-01 17:14:20 +08:00 1
解耦 异步 削峰
+ 多语言协作。 |
39
northisland 2020-12-01 17:15:17 +08:00
@walsh 贫乏的汉语
|
40
julyclyde 2020-12-01 17:32:27 +08:00
1 削峰
2 耗时长的任务,把交付任务和取得结果两个步骤分离 3 解耦合 削峰场景下,越积越多时可以扩容 consumer 或者缩减 producer 解耦合场景下,队列可以作为一个性能测量点。前后两个部分可以分别进行测试调试 |
41
nanjingwuyanzu 2020-12-01 17:35:27 +08:00
解耦 削峰 非实时统计的数据可以走 mq
|
42
hws8033856 2020-12-01 17:43:42 +08:00
把消息队列比喻成水库你就明白了
|
43
astkaasa 2020-12-01 18:03:28 +08:00
削峰填谷
|
44
laminux29 2020-12-01 18:17:54 +08:00
把 Factorio 玩一遍你就懂了,这游戏能让你直观感受到用不用队列的差别。
|
45
iColdCat 2020-12-01 18:23:25 +08:00
削峰啊 上游服务的流量并不一定一直是很高的 可能只是在某个时间段内高 那你为了这某个时间段的高流量去提升下游服务的配置就显得不是那么划算了
|
46
lepig 2020-12-01 18:23:46 +08:00
并行转串行?
|
47
beryl 2020-12-01 18:28:53 +08:00
上游不会一直大于下游的处理能力,削峰填谷的还一个点是时间的错峰,整点上游并发大,阻塞在消息队列里面,下游可以分散时间处理
|
48
liudaolunhuibl 2020-12-01 19:00:03 +08:00
举个例子,我一个电商系统,客户下单之后有:计算积分、通知库管系统准备出货并且存量-1,自动领取一些优惠卷等操作,如果是微服务架构那么这些操作肯定是放在对应的服务上面的,如果假如说我们不用消息队列的话那么订单系统怎么通知这些服务做对应的操作呢?我能想到的是调用 Http 接口( fegin )或者 rpc 调用( dubbo ),刚上线的时候我服务是单节点还行没啥问题,到了后面生意越来越好了我要做集群了,那么我就要保证我通知下游系统的接口是幂等的因为每个节点都可能调用,到了后面下单之后的操作越来越多(该死的产品经理),甚至是有部分下游系统不在我微服务里我要用 restTemplate 去调用了,这样又有了新问题:每接入一个新服务我都要去修改代码去和其他服务对接口然后联调,然后因为下游服务越来越多我的订单服务在双十一这种流量洪峰的时候已经快扛不住了,那么怎么解决?对,我可以导读抽出一个通知服务,让订单服务调用通知服务的接口获取订单信息,我下游系统去和通知服务进行对接,但是通知系统要不要持久化这些订单信息?万一下游系统挂了我的通知系统怎么去重复通知呢?怎么保证我的订单信息不丢失呢?消息队列就出来了,他实际上就是人家帮我们做好了的通知系统,他可以保证消息的重复消费、持久化、重试。并且自身也可以集群的。
|
49
liudaolunhuibl 2020-12-01 19:01:32 +08:00
并且用消息队列还有个好处就是,你不需要定义“接口”,我只需要定义消息,下游系统直接消费我的消息就可以了,我不用对接口不用联调了,每接入一个新下游服务他们只需要去消费对应的消息就可以了,代码维护性也大大提高了
|
50
Anarchy 2020-12-01 19:04:15 +08:00 via Android
和实际生活中的排队解决的问题一致,可预期可控。
|
51
liian2019 2020-12-01 19:09:31 +08:00
服务之间聊天用的
|
52
sampeng 2020-12-01 19:29:15 +08:00 via iPhone 2
解耦我觉得算是副作用,不是消息队列的主要作用。因为这个一搞不好就不好调试,重试容错,失败策略都极其男做,解耦把研发解成 sb 了。其实你换个角度,直接调用也算是消息队列。这个队列是在系统 tcp 层给你干的。
我个人认为所有不是为了削峰平谷用消息队列的一概是炫技,反正 3-5 年后这一块不一定还是自己维护。只要帅就够了。 上游多的时候,好的系统可以弹性伸缩,消费者自动增加。当然也不能无上限,上限是数据库的瓶颈。这个时候在一定阈值的时候会触发告警让 ops 或者研发上线关注堵塞情况。根据情况处理。而不会我本来写入只能 100 歌。突然来一万个导致写功能完全崩溃。这是很多场景下不能接受的。有同学会杠,那我直接调用也可以弹性伸缩啊。对,是可以,但是不一定来得及。怕你们是没有被突然 10-20 倍压力在 5 分钟内灌进来过…这不算什么。100 倍都有可能。弹性伸缩?你试试 10 秒内起 10 个 java 系的微服务或者 5 分钟内 100 台机器上千个微服务。而且马上全功率提供服务。所以没有支付系统是直接调用的。都是消息队列。结耦有毛线关系…就是怕挂了。 反过来,上游少,下游多。这是资源浪费,这是 ops 的活,和你没关系… |
54
sampeng 2020-12-01 19:30:59 +08:00 via iPhone
@liudaolunhuibl 嗯,我们试过 10 个接口本来同步很简单搞定的。硬要设计成消息队列。还不是乖乖改回去。千万别这么做…会累死。
|
55
liudaolunhuibl 2020-12-01 19:45:27 +08:00
@sampeng 代码层面主要是考虑维护性,你现在是十个接口,如果后面越来越多了呢?然后比如说你知道这十多二十个接口,那你离职了后面的人呢》这个太考验文档性了,再比如说,我十个接口中有一个系统要下线了或者重启了,那你调用接口不久疯狂报错了吗?虽然可能是异步的不影响,如果用消息队列的话对接 message 就可以了,就算下游系统下线了没关系,并且 mq 还可以帮你解决重复消费、重试等问题
|
56
shawnsh 2020-12-01 19:52:07 +08:00
消息队列还有几个功能,比如进程通讯,任务易管理
|
57
sampeng 2020-12-01 19:56:19 +08:00 via iPhone
另外我想说楼主,难道你们没监控吗?这压根就不是问题啊。积累了告警啊…
|
58
locochen 2020-12-01 20:07:08 +08:00 via iPhone
可以搞供给侧结构性改革
|
59
dddd1919 2020-12-01 21:54:59 +08:00
非常常见的解耦场景:一个生产方对应多个消费方
|
60
milukun 2020-12-01 23:41:37 +08:00
爬虫场景,数据抓取之后需要存储的数据库。
但是数据库不止有一种,有存储全文的 es,也有存储提取到数据关键内容的其他数据库等等。 这时候一个生产者(爬虫)就可以通过消息队列的订阅模式接入多个消费者(不同的数据库) 同时如果数据库挂掉,消息队列可以暂时起到存储的作用,等数据库恢复以后重新上数据。否则存储失败,抓取到的数据就丢失了,有些时候抓取需要一次成功。 |
61
xcstream 2020-12-01 23:46:15 +08:00
削峰填谷
|
62
AX5N 2020-12-02 00:02:17 +08:00
经常能见这种奇怪而又基础的问题,你们是没学过操作系统这门课吗。
|
63
akira 2020-12-02 01:42:27 +08:00
缓冲呀
|
64
neptuno 2020-12-02 09:36:23 +08:00
@Joker123456789 "直接调用下游服务,让下游服务去处理啊? 下游服务也可以负载均衡,动态扩容啊",例如支付成功回调,如果没有消息队列,你要调用仓库发货,调用订单接口,调用各种接口,多个系统就强耦合了。有了消息队列,你只要发送支付成功消息,各个系统收到消息后自己处理相应的逻辑即可
|
65
zarte 2020-12-02 09:52:44 +08:00
个人觉得主要是削峰填谷,长时间爆满就告警。解耦这要看水平,没啥经验的就不要硬上了大大的坑,对你或者负责实际开发的人。
|
66
TheWalkingDead 2020-12-02 10:00:39 +08:00 4
这就是为什么现在很多中小公司不想招应届生的原因了。
|
67
zxCoder 2020-12-02 10:10:27 +08:00
缓冲吧
|
68
holycrazy 2020-12-02 10:23:21 +08:00
主要是一个解耦和调度的问题。有了消息队列,相当于有了一个缓冲区,完事好商量,还能做好不同消费者之间的调度问题,这样代码只要写好业务逻辑就行了。
|
69
ming7435 2020-12-02 10:36:55 +08:00
@a719031256 这就是在扯淡了,稍微上点规模的系统都会使用消息队列好吧,起码我经历过的电商平台、支付平台、运营商系统都在规模使用,绝不仅仅面试使用
|
70
litujin1123 2020-12-02 10:37:55 +08:00
问这个问题,估计没被坑过,和用过队列吧?
|
71
refkent 2020-12-02 10:39:21 +08:00
4 点:
( 1 ) 程序、模块之间的耦合性大大降低; ( 2 )消息、事件、请求的顺序性和数据可恢复性 ( 4 )异步通信能力 ( 5 ) 缓冲能力,也就是抗压能力 |
72
summersnow521 2020-12-02 10:45:13 +08:00
还以为一楼直接:削峰平谷、异步处理、解耦,然后引的大家点赞就结束了,没想到下面一堆答案🐕
|
73
SwainWong93 2020-12-02 10:50:31 +08:00
想起上学的时候,写个计算器,问老师为啥要分 MVC ?
|
74
dvaknheo 2020-12-02 11:08:59 +08:00
小应用,用 mysql 做消息队列够了,需要用其他高级方案么
|
75
securityCoding 2020-12-02 11:14:17 +08:00
@walsh 互联网很多冒出来的理论很多都是计算机体系底层早就开始实践了的。
比如缓存-》 cpu cache,linux 的管道-》流式计算 |
76
iConnect 2020-12-02 11:19:09 +08:00 via Android
不需要很玄虚的理解,就是和食堂排队买饭一样。
一下课全翁上去买饭,乱城一锅粥,可想而知。 |
77
a719031256 2020-12-02 11:31:25 +08:00
@ming7435 我上一个项目就有用这个,7 个子系统的分布式项目,但我发现不用这个消息队列更好,现在客户那边让我们这边优化,还好我调到另一个项目去了,不然现在掉头发的就是我了
|
78
lqw3030 2020-12-02 12:58:28 +08:00 via iPhone
削峰是一个很重要的,让下游的需求平均化
|
79
sockpuppet9527 2020-12-02 13:00:19 +08:00
我想了目前我用到的两个场景:
1. 当你有 DMA 控制器的时候。 2. 当你有 AVX512 的时候。 |
80
msg7086 2020-12-02 13:06:28 +08:00
> 为什么不直接让生产者调用消费者?
其实直接调用的话,消费者处理不过来的时候,也会进消息队列。 这个消息队列就是操作系统的套接字队列。 比如你访问一个网站,有时候网站压力大,你就会等好几秒才看到内容,这个等待的过程也是消息队列。 你上传一个大文件,可网络就这么快,再快了也传不出去,最后只能卡在网卡的口子上慢慢发送,这个口子是发送缓冲区,也相当于是消息队列。 在你认为不需要消息队列的地方,其实都有消息队列。只不过他们不像那么大一个消息队列服务那样博眼球,而是都在背后默默工作。他们都是变相的队列。 |
81
yogogo 2020-12-02 13:20:18 +08:00 via Android
@a719031256 在支付系统里,队列实在是太好用了
|
82
laike9m 2020-12-02 14:00:53 +08:00 via Android
解耦,方便扩展
|
83
night98 2020-12-02 15:12:55 +08:00
很简单的例子,去火车站排队买票,在大部分时候都只会有一个人去买票,所以是够用的,等到节假日的时候,就有很多人了,这时候就只能排队等候买票,等这波过完了,还是可以正常直接买票的。
其次在业务中,很多时候新增功能就不再需要修改生产者代码了,按照你所说的生产者直接调用消费者,是需要修改生产者的代码的,而使用队列的话,就不需要修改生产者代码了,例如 rocketmq 可以新增一个消费类型 在实际业务中,例如支付业务,支付完成后发一个消息到业务方,现在新增需求,需要统计支付渠道和金额数据,这时候直接新增一个订阅消息的消费者就行了,不需要修改生产者的代码。 |
84
Flourite 2020-12-02 15:31:12 +08:00
解耦 /写缓冲,你说的情况太理想,实际情况一般都是突发大量写,其他情况都是小水流
|
85
mingl0280 2020-12-02 15:45:54 +08:00 via Android
消息队列适用于突发大规模生产的情况,此时下游来不及处理,那么消息队列可以保证消息不丢失。
例如我有个指纹传感器,下游处理程序的运行速度是 15fps,上游图像传感器没有手指的时候是 1fps,有手指可以瞬间跑到 60fps 但是只持续不到 1 秒,这个时候就可以用更便宜的 dsp 来处理数据…… |
86
wizardoz 2020-12-02 16:06:58 +08:00
蓄水池有什么用呢?直接从上游的水放到用水的地方不就行了
|
87
lolizeppelin 2020-12-02 16:22:02 +08:00 2
楼上说的那么多都是后话,甚至还有人说只有面试有用。
如果没有消息队列 1 rpc 无论走 grpc 还是 http 自己需要做通信模型 2 如果需要请求确保达到(不幂等消息),需要做确达机制 3 性能要求高,需要实现负载均衡和集群 4 实现常用的广播,按主题、前缀广播 5 目的地(消费者)掉线或者来不及相应,需要缓存堆积到队列 上述功能都是常见的需求,满足这些需求的通用组件叫“消息队列”而已 不用消息队列你就得自己实现上面这些乱七八糟的功能, 大部分情况下自己写的玩意就是劣质低功能版的消息队列 各种消息队列以及对应的使用模型无非都是更加适合某种情况而已 rabbitmq 这种就是特别看中消息确达 kafka 就是特别注重性能 不要专注的名字和名词解释上,写多业务就知道各种东西都是用来满足业务需求的 能问出这个问题说明业务写得少或者想太少 |
88
lolizeppelin 2020-12-02 16:38:12 +08:00 1
顺便补充下,其实所有思路都是一致的
cpu 为什么不直接调用硬盘?硬盘太慢怎么半加个缓存 ,缓存就叫内存 内存还是太慢 加个 cpu 缓存, 一级缓存还不够,再来二级 三级 硬盘还是太慢?记得当年的 ssd 缓存硬盘不? 用阵列卡还有阵列卡缓存 对应到“所谓的生产者消费者”不是一个道理么? 各种大型系统不也是不行就加一层缓存不够再加一层么 消息队列就是这加的一层而已 大型系统中间商肯定是必须存在的 你看现实里消费者也不是直接去工厂拿货呀,买显卡还会被耍猴呀 |
89
lzyliangzheyu 2020-12-02 17:47:08 +08:00
怕来不及处理丢数据。。。。晚处理总比不处理的好
|
90
Joker123456789 OP @wizardoz 本来就可以啊,有什么问题吗? 蓄水是因为下游 有时需要水,有时不需要水。 就是个仓库的作用。
但是程序中,消费端是不停的在消费的。 完全两个概念。 我感觉你只看了一眼标题就回答了,没看我的详细描述。 我的问题是基于详细描述的那个前提的 |
91
Aresxue 2020-12-03 10:29:40 +08:00
因为现实中流量是极其不均匀的,消息队列不是为了技术出现的,是为业务出现的
|
92
stevenkang 2020-12-03 11:16:01 +08:00
学校食堂打饭,排队和不排队得区别。
虽然阿姨打饭得速度没变,但整体效率似乎区别很大。 同样得,十字路口,没有红绿灯不用排队等得话,想想啥效果。 |
93
zycode277 2020-12-03 13:02:34 +08:00
削峰
|
94
onetheway 2020-12-03 17:04:38 +08:00
@lolizeppelin 老哥说的有道理的
|
95
MortyP 2020-12-03 19:27:32 +08:00 via Android
三峡大坝也是有用的
|