01 | 为什么需要消息队列?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
消息队列在系统通信中起到重要作用,本文通过生动的例子和技术细节清晰阐述了消息队列的作用和适用场景。首先,消息队列适用于异步处理,如秒杀系统中通过消息队列实现服务的异步处理,提高系统性能。其次,消息队列也适用于流量控制,可实现削峰填谷的作用或使用令牌桶控制流量。另外,消息队列还能实现系统应用之间的解耦,避免系统耦合过于紧密的问题。文章指出消息队列最常被使用的三种场景:异步处理、流量控制和服务解耦,同时也提到了消息队列的其他应用场景。然而,消息队列也存在一些问题和局限性,如引入延迟、增加系统复杂度和可能产生数据不一致等问题。因此,选择合适的架构才是体现架构师功力的地方。读者可通过思考题来思考在其工作或学习中,哪些问题可以通过引入消息队列来解决,以及已使用消息队列的系统中对应的场景。整体而言,本文通过生动的例子和清晰的阐述,使读者能够快速了解消息队列的作用和适用场景,以及消息队列在系统中的作用和可能带来的新问题。
《消息队列高手课》,新⼈⾸单¥59
全部留言(181)
- 最新
- 精选
- 小伟个人的体会,消息队列的本质是将同步处理转成异步处理,异步会带来相应的好处,但也有弊端。 Pros: 1.可在模块、服务、接口等不同粒度上实现解耦 2.订阅/消费模式也可在数据粒度上解耦 3.可提高系统的并发能力,集中力量办大事(同步部分),碎片时间做小事(异步部分) 4.可提高系统可用性,因为缓冲了系统负载 Cons: 1.降低了数据一致性,如要保持强一致性,需要高代价的补偿(如分布式事务、对账) 2.有数据丢失风险,如宕机重启,如要保证队列数据可用,需要额外机制保证(如双活容灾) 总体来说,消息队列的适用场景还是很多的,如秒杀、发邮件、发短信、高并发订单等,不适合的场景如银行转账、电信开户、第三方支付等。关键还是要意识到消息队列的优劣点,然后分析场景是否适用则会水到渠成。
作者回复: 总结到位,赞👍。
2019-07-2419210 - beiler还有个问题,如果消息量特别大的时候,消息是适合存在到redis中还是适合存到rabbitmq中?必定您在文中提到一个词,小仓库,如果货量大了怎么办?
作者回复: 首先redis肯定是不适合存消息的,虽然redis性能很好,但那是和主流的数据库比,一般大概能到几万tps左右;而现代的消息队列都能很轻松的做到几十万tps级别的性能。 消息量特别大的时候,需要考虑使用有消息堆积能力的MQ,因为一旦消费慢,大量消息就会堆积到MQ中,这种情况不太适合用RabbitMQ,可以考虑RocketMQ、Kafka和Pulsar。
2019-07-25889 - 游弋云端是否可以利用共享内存、RDMA加速消息队列的性能,老师在这块有没有实践经验?
作者回复: 如果你说的共享内存指的是PageCache,很多消息队列都会用到,RDMA据我所知常见的几种消息队列应该都还没有使用,像Kafka它在消费的时候,直接使用Zero Copy,数据直接从PageCache写到NIC的缓冲区中,都不需要进入应用内存空间。 另外,现代的消息队列瓶颈并不在本机内存数据交换这块,主要还是受限于网卡带宽或者磁盘的IO,像JMQ、Kafka这些消息队列,都可以打满万兆网卡或者把磁盘的读写速度拉满。
2019-07-24859 - beiler令牌桶给了我很大的启发,我们可以在策略中心设置令牌桶,然后通过令牌桶控制整个job的产出和数量。这样就不会经常有几百万个job了,缓存的压力也会大幅度减小。但是有一个很诡异的问题,就以秒杀系统为例(我们的系统要比秒杀复杂点),我发现这种异步系统如果需要统计任务数量的时候经常会计数不准,尽管在计数的时候我选择了原子操作,但是计数还是会出现不准的现象。这个让我很苦恼,而且往往是运行很久的任务会出现不准,往往只有在任务结束的时候发现任务不准,这个问题很难查,请问老师有什么好建议吗
作者回复: 如果计数只是为了控制流量,没必要那么精确。 如果计数是业务需求必须要求准确,简单一点的话,可以使用Redis的INCR命令来计数,这个是可以保证原子性的。Redis性能要是不能满足要求,也可以用Kafka+flink集群来解决。这两种方案都是可以保证完全准确计数的。 另外,计数不准的问题,并不一定是计数模块本身的问题,还要查一下是不是系统的其它部分有bug,导致重复计数或者漏计。
2019-07-25452 - 撒旦的堕落我懵的地方就是用队列 将同步改成了异步 那么原来同步的request 和response是一对 那么改成异步后 怎么通知用户 难道还用原来的那个response ? 还是当秒杀成功后 根据用户的id 查询到信息 比如手机号码 然后发短信给他 或者是向用户推消息什么的
作者回复: 对于网关某一个处理前端请求线程来说,大致的流程是: 0.收到Request 1.发消息 2.阻塞等待,直到超时或者收到后端的秒杀结果; 3.返回Response
2019-07-311639 - linqwAPP⇆网关--生产-->消息队列--消费-->秒杀服务,有几点疑惑,老师有空帮忙解答下哦 1、海量的请求都放在消息队列中,消息队列的整体容量如何衡量了?消息队列不可能能存放无限的消息,消息队列满应该也会有拒绝策略,比如线程池的任务队列,任务队列满,并且超过最大的线程池数,四种的拒绝策略。 2、APP响应超时,即网关超过一定的时间没有返回,消息还在任务队列中,还是会被秒杀服务处理,这样的话,返回给APP秒杀失败,但是秒杀服务已经消费了消息?难道是在网关做补偿么?如果连接已经断开,将秒杀服务对此消息的处理做回滚操作么? 3、网关和秒杀服务是通过消息队列进行通信,那响应消息也通过队列进行返回么?队列中会有APP对应的地址比如IP之类的?那这样的话,APP的海量连接都同时连接着网关,不是会有问题么? 4、消息队列应该也会做多备的策略?比如队列消息的服务挂了,那些消息全部不见,这样不是也会存在问题么?
作者回复: A1:实际上,只要有足够的磁盘容量,消息队列确实可以存放无限的消息。像秒杀请求这种数据,峰值并发高,但总数据量并不是很大,所以,堆积在消息队列中完全没问题。 A2:都按照秒杀失败处理即可。 A3:响应一般采用RPC来实现。超时或者返回秒杀结果之前,网关和APP确实要保持连接,这是HTTP协议决定的。至于网关能不能承受海量的APP连接,这个应该不用担心,网关的作用就是用来抗海量连接的,它也会有各种方法来解决这个问题。 4、是的,大部分生产系统中的消息队列要配置成集群,确保可用性和数据可靠性,这个后面的课程我们会讲。
2019-07-301431 - 白小白现在用的消息队列主要是做数据异步传输用的,之前也做过多个系统之间的解耦。看到用消息队列做秒杀系统,忽然想到之前只想过用redis去做,利用redis去做了流量的把控。不过细想想,这种情况下的redis和文章中的令牌桶很像……
作者回复: 是的,令牌桶可以用消息队列实现,也可以用Redis实现,你也可以写一个简单的令牌桶服务,原理是一样的。
2019-07-23330 - 小趴菜~生产项目中用到了kafka, 1 异部的处理交易:提高用户请求的响应速度,同时也提升了用户的体验感。 2 削峰 :保护服务器的一种方式,用户的请求放到kafka中,交易服务根据自己服务器的消费能力来消费交易数据。 3 项目的解耦:交易服务和后续的服务之间是通过Kafka进行交付,当一个服务为多个服务提供数据的时候,可以通过MQ进行交换来解耦服务间的耦合。
作者回复: 总结的很赞!
2019-07-2325 - 落尘kira看了下评论,我就简单补充一下实际用过的场景: 1.数据同步:包括业务服务之间的业务数据同步(主要是状态)、DB间的数据同步等等 2.异步通知:包括发送IM消息、异步日志、异步短信/邮件(尤其是批量数据)或注册/开启任务等等 3.信息收集:主要用于数据统计、监控、搜索引擎等等 4.服务解耦:主要用于重构和新设计时,对频繁变动的接口服务进行解耦(通常是被需求给逼的) 5.分布式事务消息:尤其是对数据一致性有要求的异步处理场景 6.主动性防御:秒杀、限流
作者回复: 总结的非常到位!
2019-07-30423 - ly老师,关于第二点的流控有点疑问:网关将request信息放入mq中,然后后端服务去mq中消费这个请求,我通常晓得的mq储存文本消息,那这样的场景下,后端处理完秒杀以后,是如何得到response响应客户端的请求呢?
作者回复: 这个取决于网关是如何实现的。大致的思路是,网关会把用户的request缓存起来,然后发消息,至于发的消息内容不一定就是这个原封不动的request对象,只要把Request中必要的信息发给后端就可以了。 后端服务可以用RPC通知网关秒杀结果,网关收到结果后找到对应的Request来构建Response返回即可。
2019-07-25922