1、为什么使用消息队列

消息队列的本质:先进先出的数据结构
用到分布式项目中,进行数据传递,数据用消息的形式封装起来放到队列里提供消费
应用场景:
解耦:实例就是比如在订单系统和支付系统、库存系统、物流系统中间加一层MQ
异步:当用户提交请求时,订单系统处理并返回,并不依赖于支付系统、库存系统、
物流系统返回的数据,说白了就是这些数据就需要存到库里,或者日志数据,
那异步最好,否则就得用同步,看具体业务场景。
削峰:秒杀场景,某一时间点,请求流量大,用MQ削峰,用户请求的数据缓存在MQ
消费者可以配置限流,
比如正常时段QPS是1万,最高峰是10万,应对流量高峰配置高性能的服务器不划算
公司会考虑经济,此时可以使用消息队列削峰。

2、消息队列的比较

产品:ActiveMQ  RabbitMQ  RocketMQ  kafka
关于选型,根据以下指标:
开发语言:
单机吞吐量:
时效性:
可用性:
功能特性:

总结怎么选:
ActiveMQ现在不怎么用了,对高并场景没有大规模的验证,社区也不活跃,并发不高
的场景可以考虑

RabbitMQ有二次开发的需求不是特别推荐,除非erlang语言玩的牛逼,单从追求性能
稳定,社区活跃的角度可以尝试选择

RocketMQ如果想二次开发,JAVA语言写的,阿里内部也验证过高并发场景,稳定性和
性能都还不错,想功能多点,可以尝试选择

kafka大数据领域,实时,日志采集


特性

ActiveMQ

RabbitMQ

RocketMQ

kafka

开发语言

java

erlang

java

scala

单机吞吐量

万级

万级

10万级

10万级

时效性

ms级

us级

ms级

ms级以内

可用性

高(主从)

高(主从)

非常高(分布式)

非常高(分布式)

功能特性

成熟,并发小可以,对大并发未测试,文档多,协议支持好

基于erlang开发,并发能力强,性能好,延时低,管理界面丰富,针对java程序员二次开发不友好

MQ功能多,阿里进行二次开发,优化之后单机吞吐量会有很大变化

只支持主要MQ功能,一些消息查询没有功能提供,为大数据准备,大数据领域应用广

3、消息队列的优缺点

其实主要的是突然加了这个MQ,那么对整个架构来说,到底有啥需要注意的,
也就是对缺点的考虑


优点:解耦、异步、削峰

缺点:

  • 系统可用性降低

        主要是针对如果MQ挂了怎么办,引出高可用的问题

 怎么保证高可用

  • 系统复杂度提高

       因为是对数据封装,那么消息丢失怎么办,重复消费怎么办,

怎么保证消息的顺序性

  • 一致性的问题

怎么保证数据一致性


怎么保证高可用: 搭集群
RabbitMQ的集群,镜像集群(生产多镜像集群,可以自己找资料)
RocketMQ的集群,双主双从
原理:Producer通过Name Server来知道我到底要向哪个Broker发送消息
可以理解为Name Server是管理者,那么Name Server怎么知道哪个
broker活着呢,是因为broker要定时向Name Server发心跳,所以
最后得保证Name Server的高可用和broker的高可用,可以搭建Name Server
的三节点集群,broker双主双从,两master两slave,master向slave同步
数据
怎么保证消息不丢失
消息为啥会丢失
三个环节:
1、生产者到MQ这段,MQ接受不到
2、到达MQ还没持久化,MQ宕机了
3、MQ到消费者,MQ发送了消息,消费者接受异常,宕机了,
MQ认为给你了,然后把消息删除了
怎么保证不丢
发送方发送消息,MQ收到,返回确认信息,
MQ进行消息持久化(如果在持久化过程中宕机?这时高可用就派上
用场了,假如说总共10Master,然后在同一时间都挂了,那就点背
吧,喝凉水塞牙了,极端情况排除,这世界谁也做不到完全完美)
MQ收到消费方的ACK确认在删除本地消息
消息重复怎么办(怎么保证幂等性)
产生重复消息是会发生的,网络问题,这句话这么说,没办法保证消息不重复,
但可以保证重复了通过技术手段来不影响业务

场景1:生产者给MQ发消息,MQ确实收到了,也要给生产者回复确认,但此时
不幸网络就出问题了,生产者接受不到,那么会在给MQ发,那么就重复了

场景2:消费者回复确认ACK消息时,MQ没收到,导致MQ的本地消息不会删除
那么消费者可能就会产生重复消费同一条消息
解决办法:
发送消息时携带一个全局唯一的id
获取消息时先根据id在redis/db中查询是否被消费过
如果没消费过,正常消费,消费完,写入redis/db中
如果消费过,那就丢弃
怎么保证消息的顺序性
怎么理解顺序性
比如订单创建、订单付款、订单完成,生产和消费都是带有顺序的
怎么保证顺序性
都保证不了消息顺序到达(一个生产者给两个MQ发)
可以保证消息顺序到达,但保证不了顺序消费(一个生产者给一个MQ发)
生产者:MQ:消费者 ———》 这种可以保证顺序消费,但容易消息堆积,还不能并行,违背初衷了
解决办法:
根据在代码(参考rocketMQ发送方源码)中传入不同的id,然后会发送到不同的队列中(id%mqs.size()取模),保证
并行消费,然后消费方代码(参考rocketMQ消费方源码)再通过分段锁保证顺序消费
注意的是,消费完要ACK确认,然后释放锁,才能进行顺序消费

怎么保证数据一致性
分布式事务来保证
比如库存服务和订单服务,跨数据库,要么同时成功,要么同时失败

消息队列总结_高可用

消息队列总结_消息队列_02