1.为什么要用MQ?
最主要的原因在三个方面:解耦、异步、削峰
解耦:
假设现在A系统要发送数据到BCD三个系统,通过接口调用的方式发送,那么问题来了,如果E系统也要这个数据呢?如果C系统不要这个数据呢?为了处理这种耦合关系,就用到了MQ。如果使用MQ,A系统发送一条数据到MQ里面,谁需要就去MQ里面消费,这就是解耦。
异步:
假设现在A系统接收到一个请求,需要本地落库,也需要在BCD三个系统落库,本地落库时间只有几毫秒,而BCD三个系统用的时间较多,就会给用户一种感觉,只是做一个简单的操作,却需要等待那么久,使用了MQ之后,就把在BCD落库的请求发到MQ中,就大大提高了系统的响应时间。
削峰:
这个比较简答,就是减少高峰时期对服务器的压力。例如双十一期间,用户大量进行购物,就可以把请求发送到MQ中,而不是直接访问服务器,这样就可以避免因为请求过多而导致服务器崩溃。
2.MQ有什么缺点?
系统可用性降低:系统引入的外部依赖越多,越不可靠。例如MQ挂了,整个系统就瘫痪了。
系统复杂度提高:加入MQ,就需要考虑消息是否被重复消费?如果消息丢失了怎么处理?如果保证消息的顺序?需要考虑的问题增多了。
一致性问题:使用了异步,就可能导致A系统落库成功了,消息发到MQ中,就返回成功了,但是B系统失败了,就会导致数据不一致问题。
3.MQ如何保证高可用的?
RabbitMQ是比较有代表性的,我也比较熟悉RabbitMQ,下文就以RattitMQ举例。
RabbitMQ有三种模式:单机模式、普通集群模式、镜像集群模式。
首先单机模式,生成环境没什么人用单机模式,一般只是Demo或者学习,这里就不说了。
普通集群模式,就是在多个机器上启动多个RabbitMQ实例,创建的queue,只会放在一个RabbitMQ实例上,但是每个实例都同步queue的数据。消费的时候,如果连接到了另外一个实例,那么这个实例会用queue所在的实例上拉取数据过来。这个方案主要是提高吞吐量的,也就是说让集群中多个节点来服务某个queue的读写操作。
镜像集群模式,一般而言,这种模式才是高可用模式。和普通集群模式不同的是,创建的queue会存在于多个实例上,就是说每个RabbitMQ节点上都包含了这个queue的全部数据。我们每次写数据的时候,就会自动把消息同步到多个实例的queue上,在配置文件中可以指定数据同步到所有节点或者是同步到指定数量的节点。这样的话,就保证了任何一个机器宕机了,都能确保其他机器中存在queue的完整数据。坏处在于,对系统的性能开销太大了,需要把数据同步到所有机器上,就导致网络带宽压力和消耗很大。