🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
从上一章,大致已经知道消息队列是什么。 而本章,讲述消息队列在实际项目中的价值,即应用场景。 > 在合适的时候,引入消息队列,能让我们的服务架构可用性更高,能力更优秀。 下面,一起来了解消息队列的应用场景。 # 数据冗余 我们可能在看到“冗余”这个词的时候,觉得他是个贬义词。 但实际上,一定程度的冗余,会让我们的数据更加安全。 比如,数据库备份,就是一种数据冗余,mysql读写分离,亦是通过日志和轮询实现数据冗余。 **这样,当我们某一份数据出现问题时,我们还有第二份数据,数据就更加安全。** 那么,消息队列如何提供冗余功能呢? > 常见的消息队列系统,会将数据保存在内存中,以提高数据读写效率。既然数据在内存中,就可能出现丢失的情况,所以,它们又提供持久化的功能,保证在队列系统崩溃后,数据仍然存在。 > 另外,消息队列内的每一条消息,都必然存在 reserved 和 deleted 两个状态,只有当消费者给队列系统发送处理成功的信号时,消息才会从队列中删除,并不会因为消息已接收,就删除消息。 可以说,消息队列,也是增对数据库层的一道输入向缓存,对数据有冗余作用。即,当有数据需要进入数据库,会先经过消息队列,再进入数据库。 # 解耦合 我们知道软件工程讲究**高内聚低耦合**,所以我们会想许多办法来控制耦合度,即解耦。 消息队列,也是一种解耦的方案。 按照普通流程,**消费代码**可能会直接跟在**生产代码**后面,那么,生产和消费就成了彼此的上下文,甚至连变量、作用域等都会有依赖,此时,你若对生产代码的某个变量进行修改,你必须仔细检查消费代码是否也使用了这个变量。 > 通过消息队列,我们将生产代码和消费代码拆分开来,它们不再互相依赖彼此的具体实现,只依赖于消息队列中**消息的结构**。只要消息结构不变,生产代码和消费代码如何修改,都不会影响到彼此。 这一点,我们可以联想到上一章《什么是消息队列?》中的下单功能辅助理解。 # 异步能力 有人说,**高性能离不开异步,异步离不开队列**。 一定意义上来说,这句话是很有道理的。 异步,它让每一个调用都能及时返回,提升响应速度。在这里,可能需要理解一下异步:[《关于异步的理解》](https://www.jianshu.com/p/1593a1d2c002) 队列,保证了异步调用的处理不会丢失。这句话中的“处理”一词,指处理工作,是个名词。 > 我们知道,异步,它先返回的是调用动作是否成功的结果,而具体调用执行的逻辑和结果,并不在这里返回,而是以通知(回调)的形式进行。队列,是确保每一个调用的处理都会被执行数据结构。 这一点,我们可以在之后消息队列的实践中,体会到。 消息队列,能够让在架构上提供异步能力(注意,是架构上,而非代码层面如函数调用的异步能力)。 关于这个异步能力,还是可以参考上一章《什么是消息队列?》中的下单功能, # 扩展性 当架构中加入消息队列,生产者和消费者就比较容易扩展。 仍然以下单功能举例,如果生产者和消费者的代码耦合在一起,互相严重依赖,当我们想对生产者产生内容进行不同的处理(消费)时,则需要在原有的源码中进行扩展,这对原有代码产生伤害,便不必说扩展性了。 > 但如果以消息队列将生产者和消费者进行解耦,则,我们只需要添加订阅消息的消费者程序即可,新的消费者对旧消费者没有任何伤害,它依旧依赖于消息队列,只需要确保它能收到消息即可。 # 顺序保证 队列本身具备“先进先出”的特性,消息队列是一种队列结构的中间件,则,消费者会根据消息进入的先后顺序,进行先后处理。 **其本身就能解决顺序问题** # 削峰填谷 在某些高并发的场景下,流量突然激增,比如秒杀。 此时,数据库的压力很大,而数据库的读写处理能力普遍低于内存式的消息队列。 此时,可以将消息临时存储于消息队列中,减少数据库的压力,然后再由消费者按数据库能够接受的频率去读取消息,进行处理,因为数据库只在秒杀那一刻压力很大,平时会清闲一些。 **这就是将山峰削掉,填补山谷**