MQ问题

1.项目中为什么要使用MQ。

      解耦:模块之间的调用十分复杂,同时这个调用时不需要直接同步调用接口的,此时就可以考虑运用MQ去进行系统的解耦。

      异步:如果A系统接收到一个请求,需要在自己本地写库,同时还需要调用MQ进行写库,自己需要20ms,BCD需要300ms,500ms,100ms.总共的耗时需要920ms,此时用户感觉慢死了,使用消息进行异步后 用户还是对系统A发送请求,此时第一件事,系统A执行插入SQL操作耗时99ms,然后连续发三条消息给ABC系统,耗时5ms,然后每个系统会从对应的消息队列中拉取参数,然后在自己本地执行对应的操作。计算一下一共花了25ms。点一个按钮直接就返回了,真爽。在现在的公司中,有个发布问题的业务场景,发布问题后要执行的操作比较多,涉及扣除an币,给@的人,关注的人,周边基因匹配的人,发送回答问题的邀约。  如果不使用MQ可能用户发个问题要等待很久,但是我使用了mq,将一些实时性不是很高的逻辑,放在mq中处理,用户发布一个问题,就能快速得到回应,问题发布成功,进一步提升了用户的体验。

 削峰:在执行秒杀的场景,单机数据库的每秒并发大约是2000,此时如果突然请求达到5000。。。数据库可能会宕机。此时就需要引入MQ,将用户的5000个请求写入MQ系统,然后系统A每秒从MQ中拉取2000个请求,此时如果高峰期持续了一小时,可能到时消息队列中堆积了几十甚至几百的请求。但是系统A还是会以每秒2000的速度从队列中处理,直到把堆积的消息完全处理掉。

 

2.引入消息队列带来的缺点

 系统的可用性降低: 加个MQ进来,万一MQ挂了咋整?MQ挂了,整套系统崩溃了,你不就完了么。

 系统复杂性提高:加个MQ进来,如何保证消息没有重复消费?如何处理消息丢失?怎么保证数据的顺序行?

 一致性问题: A系统处理成功直接返回,人家以为你的请求直接成功了,如果B系统写入数据失败了,数据就不一致了,同时还有重复消息,消息顺序,消息堆积等一系列问题。

 

 

3.MQ消息选型:

ActiveMQ:万级吞吐量,ms时效性,有较低丢消息的可能行,社区不活跃,基于主从架构实现高可用性

RabbitMQ:万级吞吐量,微秒时效性,erlang开发,社区活跃,提供了完善的管理界面,基于主从架构实现高可用性

RocketMQ:10万级吞吐量,ms级MQ功能较为完善,还是分布式的,扩展性好,阿里java系的,我们可以自己阅读源码,定制自己公司的MQ,可以掌控

Kafka:10万级吞吐量,ms级,一般配合大数据类的系统来进行实时数据计算、日志采集等场景,非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用,这个特性天然适合大数据实时计算以及日志收集

 

4.RabbitMQ运行机制:

 

组成部分:

Broker:消息队列的服务器实体

Exchange:交换器,RabbitMQ的内部对象,生产者客户端通过交换器将消息发送到队列中存储

Bingding:绑定,消息队列和交换机之间的关联。一个绑定就是基于路由键将交换机和消息队列连接起来的路由规则。(#匹配0个或多个单词,* 匹配一个单词)

Queue队列:用来保存消息直到发送给消费者

Channel:多路复用连接中,一条独立的双向数据流通道

 

 

5.RabbitMQ的高可用

普通集群模式:你创建的Queue,只会放在一个RabbitMQ实例上,每个实例都同步queue的元数据。当客户端消费的时候,如果你连接的时另外一个queue,这个实例会去queue所在实例上拉取数据下来。这就产生了集群内部大量的数据传输,同时可用行没有得到保障,集群中的一个实例挂掉了,如果你开启了持久化,要等到那个实例灰度,才可以继续从这个queue中拉取数据。

镜像集群模式:每一个queue都会存放到多个消息实例中,每次写数据,会自动进行多个实例的queue里的消息同步。

缺点:性能开销大,因为要通过所有机器,同时没有什么拓展性可言,新增的机器也包含了你的queue,没办法进行线性的拓展。

 

6.RabbitMQ的重复消费,保证消费者 的幂等性

     1.使用唯一键 

     2.生产者发送数据的时候,加一个全局唯一id,消费者在开始消费的时候,用redis判断,这条数据有没有被消费过,消费过,就不在消费了

 

 

7.RabbitMQ的顺序消费

执行数据库增加、修改、删除;要是换了顺序给执行成删除、修改、增加,不全错了么。

rabbitmq出现非顺序错乱的场景:一个queue,多个consumer,这不明显乱了

拆分多个queue,每个queue对应一个consumer,数据1,数据2,数据3都发送到同一个queue里面,一个消费者消费一个queue;

或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队;

 

 

8.消息堆积

1.MQ不设置过期时间,避免消息过期丢失

2.服务降级,申请十倍的MQ机器,改写原来的MQ处理逻辑,将请求转发到临时增加的机器上,新增的MQ机器然后以10倍的速度消费MQ堆积消息。

 

posted @ 2019-09-24 21:37  Jemb  阅读(372)  评论(0编辑  收藏  举报