一、消息队列简介

    现在很多企业开发项目都是分布式、微服务的了。这里就不介绍这些概念,引入这个主要是因为消息中间件可以解决系统间通信的问题。业界通信方式主要有两种:一种是基于远程过程调用也就是RPC,另外一种是基于消息队列来实现的。这里主要介绍第二种,基于消息队列的方式是指应用中的某个系统负责发送消息,由关心这条消息的相应系统负责接收消息,并在收到消息后进行各自系统内的业务处理。消息在被发送后可以立即返回,由消息队列来负责消息的传递,消息发布者只管将消息发布到消息队列中就好了,不必管由谁来取,消息使用者只管从消息队列中取消息而不管是谁发布的,这样发布者和使用者都不用知道对方的存在。主要表现如下图:

二、消息队列的作用

    消息队列就如其名所谓,消息以及队列。消息也就是需要发送出去,在另一个地方接收的不可描述的东西,面向对象语言中万物皆对象,所以就是一个实体对象。而队列是一种FIFO(先进先出)的数据结构,消息被依次放进队列,然后被依次拿出队列。这就是简单消息队列的实现,只需有生产者、存储消息的队列、消费者。复杂消息队列需要考虑很多方面的问题比如消息的可靠性、持久性、消息堆积等问题,当然我们先分析使用消息队列能干嘛。
    消息队列主要解决问题有异步、解耦、流量削峰、日志收集、事物最终一致性等问题。下面对每一个做简单介绍:
    1. 异步
    一个业务当中包含了一些实时性要求不高,且比较耗时的任务的时候,同步操作会比较耗时,造成用户体验不好。考虑到这一方面可以让实时性要求不高,且比较耗时的任务在另一个系统完成,这就让一个业务流程进行了异步。比如我在注册github用户的时候,注册完了他会发一条欢迎您注册成功的邮件给我。这个步骤同步解决的话需要先保存用户注册的信息,然后调用发送邮件的方法,最后返回用户注册成功,进入首页。假设保存用户信息用时50ms,发送邮寄用时100ms,这整个操作就用了150毫秒,具体如下图3-1。 
用户本来完全可以在50ms就返回的操作导致用了150ms,体验非常不好。这时如果我们采用异步的操作,保存用户注册的信息之后将消息发送给一个容器,然后立即返回,这是我们就只需要50ms。具体如下图3-2。       
    2.  解耦
    很多时候项目初期业务会比较简单,需要添加新的功能如果只是一直在原系统上一直改代码,慢慢的这个项目将变得非常笨重,且难以维护。每添加一个功能或者修改一个功能都需要对原代码进行修改,而且随着需求的添加,各模块之间逐渐形成相互调用关系,业务将会变得非常复杂。其实通过分析可以发现很多业务都只是需要负责好自己做的事情,完成之后只需对后面的模块发出完成通知即可,完全不需要等待后面模块完成。基于利用消息队列的模型,可以让模块形成独立演化,这样非常符合大型网站的开发。
    3.  流量削峰
    今天刚好是双十二,京东、淘宝等购物网站进行各种促销,在抢单那一刻大批量的数据涌入系统,如果没有做流量限制处理,请求直接打在系统和数据库上。毫无疑问,系统访问会非常缓慢、设计不当数据库必然会当机。常见做法是加机器等,这种做法非常耗资。引入消息队列,我们可以对进入系统的请求做严格控制,将请求先堆积在消息队列中,系统根据能处理请求的能力获取请求消息,这样就可以避免系统在高并发下变得不可用问题。
    4.  日志收集
    在项目开发和运维中日志是非常重要的部分,很多时候我们定位bug都是通过日志进行跟踪调试,定位问题所在的。在项目初期,比如我现在在帮助医院开发的系统都是自己处理日志,这种做法当然现在是没问题的,但是当需求越来越多,需要建设的系统越来越多,将会产生大量日志,管理也会越来越难。这时我们就可以选择构建的一个日志系统来支撑,提供离线和在线分析日志能力。
    5.  缓存最终一致性
    对于数据库和缓存一致性问题,一直是一个难题。我们很难保证数据库和缓存的强一致性,很多时候我们都是选择最终一致性来解决这边一致性问题。我们更新数据库和缓存的策略采用先更新数据库,再删除缓存的策略(为什么这么做?可以参考:https://zhuanlan.zhihu.com/p/59167071)。我们将需要删除的key放入消息队列中,进行重试机制,可以保证缓存的最终一致性。

附录

    1.  名词解释

    消息队列:消息队列(MQ)是一种系统间相互协作的通信机制。
    消息协议:常见的协议主要有AMQP、MQTT、STOMP、XMPP等,是一个双方通信的约定。类比TCP/IP这类网络协议。
    中间件:非底层操作系统软件、非业务应用软件,不是直接给最终用户使用的,不能直接给客户带来价值的软件统称为中间件。
    消息中间件:一个关注于数据的发送和接收,利用高效、可靠的异步消息传递机制集成分布式系统。简化了应用之间数据的传输,屏蔽了底层的异构操作系统和网络平台,提供了一致的通信和应用开发标准,确保分布式下消息可靠传输和数据交换。