目录
1. 为什么使用消息队列
-
解耦:
一旦A挂了,就会导致下游所有系统都没有数据,使用消息中间件来解耦,A只需要把数据发给中间 件,下游系统自行调用
- 异步:系统C发送个消息到MQ中间件里,由系统D消费到消息之后慢慢的异步来执行这个耗 时2s的业务处理。这种方式直接将核心链路的执行性能提升了10倍。
- 削峰:某套系统低峰期并发也就100多个,高峰期并发量会增到5000以上,而这个数据库只 支撑每秒1000左右的并发写入,一旦高峰期出现并发量很大,就容易宕机。使用MQ后,消息 被MQ保存起来,然后系统按照自己的消费能力来消费,比如每秒消费1000个,这样慢慢写入 数据库,就不会轻易宕机。
2. 消息队列的缺点
- 可用性低:本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加入个消息队 列进去,那消息队列挂了,你的系统不是挂了。因此,系统可用性会降低 。解决方法:使用MQ集群,防止一个挂了还能继续使用
- 复杂性高:需要考虑消息有没有重复消费(即消息幂等性)、消息丢失、保证消息传递性等问 题 ,为什么会出现这种情况? 正常情况下,消费者在消费完消息后,会发送一个确认的消息给消息队列,消息队列知道该消息被消费了,就会把该消息从队列删除。RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCESS。 解决方法: 如果消息是数据库插入操作,给消息一个唯一主键,如果出现重复消费的情况,会导致主键冲突,数据库避免有脏数据。如果消息是set入redis的话,是不会存在重复的,因set操作是幂等操作。 如果上面两种情况还不行,上大招。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis. 那消费者开始消费前,先去redis中查询有没有消费记录即可。
- 数据一致性问题:MQ带来系统响应提高,但是如果消息没消费,就会导致数据不统一 解决:即防止生产者弄丢数据、消息队列弄丢数据、消费者弄丢数据。消息队列一般会 持久化到磁盘,生产者数据丢失MQ事务会回滚,可以尝试重新发送。消费者丢失数据一 般都是采用了自动确认消息模式导致消费信息被删,只要改为手动即可,即消费者消费 完之后,调用一个MQ的确认方法就行了。 缺点:rabbitMQ事务开启,就会变为同步阻塞操作,生产者会阻塞等待是否发送成功, 太耗性能会造成吞吐量的下降。
- 消息队列的延时与过期失效问题: 解决:消息队列的延迟和过期失效是消息队列的自我保护机制,目的是为了防止本身被 挤爆,当然也可以关闭这个机制。但是不推荐关闭,可以改为某个消息消费失败5次后, 可以把这个消息丢弃等,但是丢弃的数据最好写个临时程序又重新放入MQ队列或记录下 来重新处理。
3. 消息队列如何选型?
更新频率:
RocketMQ
比
RabbitMQ
频繁,比
ActiveMQ
频繁 中小公司建议用RabbitMQ
,大公司用
ActiveMQ
,大数据用
Kafka
4. 如何保证消息队列是高可用的
(1)
RabbitMQ
中有三种模式:单机模式、普通集群模式、镜像集群模式。生产没人用单机模式
- 普通集群模式:默认的集群模式,对于Queue来说,消息实体只存在于其中一个节点,A、B两个 节点仅有相同的元数据,即队列结构,但队列的元数据仅保存有一份,即创建该队列的rabbitmq 节点(A节点),当A节点宕机,你可以去其B节点查看,发现该队列已经丢失。 当消息进入A节点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A、B间进行消息 传输,把A中的消息实体取出并经过B发送给consumer,所以consumer应平均连接每一个节点, 从中取消息。该模式存在一个问题就是当A节点故障后,B节点无法取到A节点中还未消费的消息实 体。如果做了队列持久化或消息持久化,那么得等A节点恢复,然后才可被消费,并且在A节点恢复 之前其它节点不能再创建A节点已经创建过的持久队列;如果没有持久化的话,消息就会失丢。这 种模式更适合非持久化队列,只有该队列是非持久的,客户端才能重新连接到集群里的其他节点, 并重新创建队列。假如该队列是持久化的,那么唯一办法是将故障节点恢复起来。
- 镜像模式:把需要的队列做成镜像队列,存在于多个节点。其实质和普通模式不同之处在于,消息 实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。该模式带来的副作用也很 明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽 将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用
- 主备模式:主节点提供读写,备用节点不提供读写。如果主节点挂了,就切换到备用节点,原来的 备用节点升级为主节点提供读写服务,当原来的主节点恢复运行后,原来的主节点就变成备用节点
(2)
RocketMQ
集群:
- 多Master模式:一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优 缺点如下:
- 优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使 机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消 息,同步刷盘一条不丢),性能最