plainify

浅入浅出消息队列

高中的时候,每节自习课都会有人零零散散的找老师问问题,一开始就一两人还好,后来渐渐的人多了,老师也烦了,你说我这上了一天的课难得晚上可以看自习休息会,这帮小崽子还一个个这么折腾人。 于是老师决定让同学们把需要提的问题写在纸上,下自习后交给课代表,然后老师再从课代表那取出要问的问题,然后再一个个解决。 相信在学生时代大家都遇到过上面的这种情况,如果我们将在学校上课抽象成一个系统,那这种情况就是一个很常见的消息队列的使用场景。 在上述实例中,要提的问题就是**「消息」,提问题的学生是「生产者」,回答问题的老师是「消费者」,收集问题的课代表是「消息队列」**。 看到「生产者」和「消费者」,不知道有没有想起来在 RPC 的中同样也有生产者和消费者,那么这两者之间有关联吗? 如果对 RPC 还不了解的读者可以阅读我之前写过的一篇文章 我们先来回顾一下,在 RPC 的调用关系里,我们把提供具体的调用方法的系统叫服务提供者(Provider),调用服务的系统称为服务消费者(Consumer)。 如果有 N 个不同系统相互之间都有 RPC 调用,这时候整个系统环境就是一个很大的网状结构,如下图所示,依赖关系有 N*(N-1)/2 个。任何一个系统出问题,都会影响剩下 N-1 个系统,这种强耦合肯定不是我们想要的,那应该怎么降低这种耦合呢? 基于这些问题,消息队列(Message Queue,简称 MQ)技术横空出世,所有的处理请求先作为一个消息发送到 MQ(一般我们叫做 broker),接着处理消息的系统从 MQ 拿到消息并进行处理。这样就实现了各个系统间的解耦,同时可以把失败策略、重试等作为一个机制,对各个应用透明,直接在 MQ 与各调用方的应用接口层面实现即可,如下图所示: 一般来说,我们把发送消息的系统称为消息生产者(message producer),接受处理消息的系统称为消息消费者(message consumer)。 一般来说,我们把发送消息的系统称为消息生产者(message producer),接受处理消息的系统称为消息消费者(message consumer)。 根据消息处理的特点,我们又可以总结两种消息模式: 点对点模式(Point to Point,PTP),一个生产者发送的每一个消息,都只能有一个消费者能消费,看起来消息就像从一个点传递到了另外一个点。 发布订阅模式(Publish-Subscribe,PubSub),一个生产者发送的每一个消息,都会发送到所有订阅了此队列的消费者,这样对这个消息感兴趣的系统都可以拿到这个消息。 使用 MQ 的好处 从上面的介绍中我们可以看出 MQ 的出现在一定程度上是可以将复杂的服务解耦。 那么回到一开始的例子,我们发现,课代表的出现也确实在一定程度上解决了老师和学生之间的强耦合关系。类似的例子还有快递柜,快递员将快递放到快递柜,不方便拿快递的人可以在下班之后再去拿快递。这样快递员和收快递的人就可以更加自主,只通过一个简单的“容器”——快递柜来联系。你甚至可以不知道你的快递员长什么样子,快递员也可以不知道你是谁,在他们眼里,都只有快递柜,没有对方。 毫无疑问,与一个简单的容器打交道,比与复杂的人打交道容易一万倍,他们也可以更加专注的去完成自己的事情。 那么除解耦外还有其他的优势吗?自然是有的。 再回到一开始学生提问的例子,我们设想另一个场景:如果提问的问题特别难,而且是每个人都要问这个问题,老师给每个人讲解要花很多时间,学生有压力,老师也会觉得麻烦,所以老师决定第二天上课的时候把这个问题单独拿出来说。 在上面这个事例中,就体现了 MQ 的另外两个作用——广播和削峰。 广播:老师只需要讲解一次,所有需要听这道题的同学就都可以听了。 削峰:将当晚那么多同学讲题的需求延迟到第二天上课。 当然,在实际的使用过程中,MQ 的用处也不只是这么些,这里推荐阅读阿里巴巴中间件团队的十分钟入门 RocketMQ 中的第一章 👉消息中间件需要解决哪些问题? MQ 的使用成本 如此一看,消息队列确实有很多好处,不过凡事皆有利弊,消息队列的使用也是有一定的使用成本的。...