消息队列高手课
李玥
美团高级技术专家
52199 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
进阶篇 (21讲)
消息队列高手课
15
15
1.0x
00:00/00:00
登录|注册

01 | 为什么需要消息队列?

令牌桶控制流量
秒杀系统
消息队列在系统中的作用
系统中引入消息队列解决的问题
数据不一致问题
增加系统复杂度
延迟问题
消息广播
连接流计算任务和数据
发布/订阅系统
服务解耦
流量控制
异步处理
服务解耦
流量控制
实现服务的异步处理
解决应用之间的通信问题
思考题
消息队列的问题和局限性
消息队列的适用范围
适合使用消息队列解决的问题
消息队列的作用
为什么需要消息队列?

该思维导图由 AI 生成,仅供参考

你好,我是李玥。今天我们来讲讲为什么需要消息队列,消息队列主要解决的是什么问题。
消息队列是最古老的中间件之一,从系统之间有通信需求开始,就自然产生了消息队列。但是给消息队列下一个准确的定义却不太容易。我们知道,消息队列的主要功能就是收发消息,但是它的作用不仅仅只是解决应用之间的通信问题这么简单。
我们举个例子说明一下消息队列的作用。话说小袁是一家巧克力作坊的老板,生产出美味的巧克力需要三道工序:首先将可可豆磨成可可粉,然后将可可粉加热并加入糖变成巧克力浆,最后将巧克力浆灌入模具,撒上坚果碎,冷却后就是成品巧克力了。
最开始的时候,每次研磨出一桶可可粉后,工人就会把这桶可可粉送到加工巧克力浆的工人手上,然后再回来加工下一桶可可粉。小袁很快就发现,其实工人可以不用自己运送半成品,于是他在每道工序之间都增加了一组传送带,研磨工人只要把研磨好的可可粉放到传送带上,就可以去加工下一桶可可粉了。 传送带解决了上下游工序之间的“通信”问题。
传送带上线后确实提高了生产效率,但也带来了新的问题:每道工序的生产速度并不相同。在巧克力浆车间,一桶可可粉传送过来时,工人可能正在加工上一批可可粉,没有时间接收。不同工序的工人们必须协调好什么时间往传送带上放置半成品,如果出现上下游工序加工速度不一致的情况,上下游工人之间必须互相等待,确保不会出现传送带上的半成品无人接收的情况。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

消息队列在系统通信中起到重要作用,本文通过生动的例子和技术细节清晰阐述了消息队列的作用和适用场景。首先,消息队列适用于异步处理,如秒杀系统中通过消息队列实现服务的异步处理,提高系统性能。其次,消息队列也适用于流量控制,可实现削峰填谷的作用或使用令牌桶控制流量。另外,消息队列还能实现系统应用之间的解耦,避免系统耦合过于紧密的问题。文章指出消息队列最常被使用的三种场景:异步处理、流量控制和服务解耦,同时也提到了消息队列的其他应用场景。然而,消息队列也存在一些问题和局限性,如引入延迟、增加系统复杂度和可能产生数据不一致等问题。因此,选择合适的架构才是体现架构师功力的地方。读者可通过思考题来思考在其工作或学习中,哪些问题可以通过引入消息队列来解决,以及已使用消息队列的系统中对应的场景。整体而言,本文通过生动的例子和清晰的阐述,使读者能够快速了解消息队列的作用和适用场景,以及消息队列在系统中的作用和可能带来的新问题。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《消息队列高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(181)

  • 最新
  • 精选
  • 小伟
    个人的体会,消息队列的本质是将同步处理转成异步处理,异步会带来相应的好处,但也有弊端。 Pros: 1.可在模块、服务、接口等不同粒度上实现解耦 2.订阅/消费模式也可在数据粒度上解耦 3.可提高系统的并发能力,集中力量办大事(同步部分),碎片时间做小事(异步部分) 4.可提高系统可用性,因为缓冲了系统负载 Cons: 1.降低了数据一致性,如要保持强一致性,需要高代价的补偿(如分布式事务、对账) 2.有数据丢失风险,如宕机重启,如要保证队列数据可用,需要额外机制保证(如双活容灾) 总体来说,消息队列的适用场景还是很多的,如秒杀、发邮件、发短信、高并发订单等,不适合的场景如银行转账、电信开户、第三方支付等。关键还是要意识到消息队列的优劣点,然后分析场景是否适用则会水到渠成。

    作者回复: 总结到位,赞👍。

    2019-07-24
    19
    210
  • beiler
    还有个问题,如果消息量特别大的时候,消息是适合存在到redis中还是适合存到rabbitmq中?必定您在文中提到一个词,小仓库,如果货量大了怎么办?

    作者回复: 首先redis肯定是不适合存消息的,虽然redis性能很好,但那是和主流的数据库比,一般大概能到几万tps左右;而现代的消息队列都能很轻松的做到几十万tps级别的性能。 消息量特别大的时候,需要考虑使用有消息堆积能力的MQ,因为一旦消费慢,大量消息就会堆积到MQ中,这种情况不太适合用RabbitMQ,可以考虑RocketMQ、Kafka和Pulsar。

    2019-07-25
    8
    89
  • 游弋云端
    是否可以利用共享内存、RDMA加速消息队列的性能,老师在这块有没有实践经验?

    作者回复: 如果你说的共享内存指的是PageCache,很多消息队列都会用到,RDMA据我所知常见的几种消息队列应该都还没有使用,像Kafka它在消费的时候,直接使用Zero Copy,数据直接从PageCache写到NIC的缓冲区中,都不需要进入应用内存空间。 另外,现代的消息队列瓶颈并不在本机内存数据交换这块,主要还是受限于网卡带宽或者磁盘的IO,像JMQ、Kafka这些消息队列,都可以打满万兆网卡或者把磁盘的读写速度拉满。

    2019-07-24
    8
    59
  • beiler
    令牌桶给了我很大的启发,我们可以在策略中心设置令牌桶,然后通过令牌桶控制整个job的产出和数量。这样就不会经常有几百万个job了,缓存的压力也会大幅度减小。但是有一个很诡异的问题,就以秒杀系统为例(我们的系统要比秒杀复杂点),我发现这种异步系统如果需要统计任务数量的时候经常会计数不准,尽管在计数的时候我选择了原子操作,但是计数还是会出现不准的现象。这个让我很苦恼,而且往往是运行很久的任务会出现不准,往往只有在任务结束的时候发现任务不准,这个问题很难查,请问老师有什么好建议吗

    作者回复: 如果计数只是为了控制流量,没必要那么精确。 如果计数是业务需求必须要求准确,简单一点的话,可以使用Redis的INCR命令来计数,这个是可以保证原子性的。Redis性能要是不能满足要求,也可以用Kafka+flink集群来解决。这两种方案都是可以保证完全准确计数的。 另外,计数不准的问题,并不一定是计数模块本身的问题,还要查一下是不是系统的其它部分有bug,导致重复计数或者漏计。

    2019-07-25
    4
    52
  • 撒旦的堕落
    我懵的地方就是用队列 将同步改成了异步 那么原来同步的request 和response是一对 那么改成异步后 怎么通知用户 难道还用原来的那个response ? 还是当秒杀成功后 根据用户的id 查询到信息 比如手机号码 然后发短信给他 或者是向用户推消息什么的

    作者回复: 对于网关某一个处理前端请求线程来说,大致的流程是: 0.收到Request 1.发消息 2.阻塞等待,直到超时或者收到后端的秒杀结果; 3.返回Response

    2019-07-31
    16
    39
  • linqw
    APP⇆网关--生产-->消息队列--消费-->秒杀服务,有几点疑惑,老师有空帮忙解答下哦 1、海量的请求都放在消息队列中,消息队列的整体容量如何衡量了?消息队列不可能能存放无限的消息,消息队列满应该也会有拒绝策略,比如线程池的任务队列,任务队列满,并且超过最大的线程池数,四种的拒绝策略。 2、APP响应超时,即网关超过一定的时间没有返回,消息还在任务队列中,还是会被秒杀服务处理,这样的话,返回给APP秒杀失败,但是秒杀服务已经消费了消息?难道是在网关做补偿么?如果连接已经断开,将秒杀服务对此消息的处理做回滚操作么? 3、网关和秒杀服务是通过消息队列进行通信,那响应消息也通过队列进行返回么?队列中会有APP对应的地址比如IP之类的?那这样的话,APP的海量连接都同时连接着网关,不是会有问题么? 4、消息队列应该也会做多备的策略?比如队列消息的服务挂了,那些消息全部不见,这样不是也会存在问题么?

    作者回复: A1:实际上,只要有足够的磁盘容量,消息队列确实可以存放无限的消息。像秒杀请求这种数据,峰值并发高,但总数据量并不是很大,所以,堆积在消息队列中完全没问题。 A2:都按照秒杀失败处理即可。 A3:响应一般采用RPC来实现。超时或者返回秒杀结果之前,网关和APP确实要保持连接,这是HTTP协议决定的。至于网关能不能承受海量的APP连接,这个应该不用担心,网关的作用就是用来抗海量连接的,它也会有各种方法来解决这个问题。 4、是的,大部分生产系统中的消息队列要配置成集群,确保可用性和数据可靠性,这个后面的课程我们会讲。

    2019-07-30
    14
    31
  • 白小白
    现在用的消息队列主要是做数据异步传输用的,之前也做过多个系统之间的解耦。看到用消息队列做秒杀系统,忽然想到之前只想过用redis去做,利用redis去做了流量的把控。不过细想想,这种情况下的redis和文章中的令牌桶很像……

    作者回复: 是的,令牌桶可以用消息队列实现,也可以用Redis实现,你也可以写一个简单的令牌桶服务,原理是一样的。

    2019-07-23
    3
    30
  • 小趴菜~
    生产项目中用到了kafka, 1 异部的处理交易:提高用户请求的响应速度,同时也提升了用户的体验感。 2 削峰 :保护服务器的一种方式,用户的请求放到kafka中,交易服务根据自己服务器的消费能力来消费交易数据。 3 项目的解耦:交易服务和后续的服务之间是通过Kafka进行交付,当一个服务为多个服务提供数据的时候,可以通过MQ进行交换来解耦服务间的耦合。

    作者回复: 总结的很赞!

    2019-07-23
    25
  • 落尘kira
    看了下评论,我就简单补充一下实际用过的场景: 1.数据同步:包括业务服务之间的业务数据同步(主要是状态)、DB间的数据同步等等 2.异步通知:包括发送IM消息、异步日志、异步短信/邮件(尤其是批量数据)或注册/开启任务等等 3.信息收集:主要用于数据统计、监控、搜索引擎等等 4.服务解耦:主要用于重构和新设计时,对频繁变动的接口服务进行解耦(通常是被需求给逼的) 5.分布式事务消息:尤其是对数据一致性有要求的异步处理场景 6.主动性防御:秒杀、限流

    作者回复: 总结的非常到位!

    2019-07-30
    4
    23
  • ly
    老师,关于第二点的流控有点疑问:网关将request信息放入mq中,然后后端服务去mq中消费这个请求,我通常晓得的mq储存文本消息,那这样的场景下,后端处理完秒杀以后,是如何得到response响应客户端的请求呢?

    作者回复: 这个取决于网关是如何实现的。大致的思路是,网关会把用户的request缓存起来,然后发消息,至于发的消息内容不一定就是这个原封不动的request对象,只要把Request中必要的信息发给后端就可以了。 后端服务可以用RPC通知网关秒杀结果,网关收到结果后找到对应的Request来构建Response返回即可。

    2019-07-25
    9
    22
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部