RabbitMQ消息队列

发布于 2017-12-19 · 本文总共 2511 字 · 阅读大约需要 8 分钟

什么时候该使用MQ?

MQ是一个互联网架构中常见的解耦利器.

什么时候不使用MQ?
上游实时关注执行结果,通常采用RPC.

什么时候使用MQ?
(1)数据驱动的任务依赖;
(2)上游不关心多下游执行结果;
(3)异步返回执行时间长;

使用场景

1.解耦:
2.异步:
3.削峰:

RabbitMQ

erlang语言开发, 基于AMQP(Advanced Message Queue Protocol)

为什么选择RabbitMQ

为什么选择RabbitMQ 现在的市面上有很多MQ可以选择,比如ActiveMQ、ZeroMQ、Appche Qpid,那问题来了为什么要选择RabbitMQ?

  • 除了Qpid,RabbitMQ是唯一一个实现了AMQP标准的消息服务器;
  • 可靠性,RabbitMQ的持久化支持,保证了消息的稳定性;
  • 高并发,RabbitMQ使用了Erlang开发语言,Erlang是为电话交换机开发的语言,天生自带高并发光环,和高可用特性;
  • 集群部署简单,正是因为Erlang使得RabbitMQ集群部署变的超级简单;
  • 社区活跃度高,根据网上资料来看,RabbitMQ也是首选;

工作原理

Producer—-connection—-Broker(Exchange、Queue)—-connection—-Consumer channel

‘exchange’—-消息转发

工作模式—-fanout发布订阅模式

工作模式—-路由工作模式 direct

工作模式—-通配符工作模式 topic

工作模式—-header-rpc工作模式

交换器分类

RabbitMQ的Exchange(交换器)分为四类:

  • direct(默认)—- direct为默认的交换器类型,也非常的简单,如果路由键匹配的话,消息就投递到相应的队列

  • fanout —- fanout交换器——发布/订阅模式

fanout有别于direct交换器,fanout是一种发布/订阅模式的交换器,当你发送一条消息的时候,交换器会把消息广播到所有附加到这个交换器的队列上.

  • topic——匹配订阅模式

RabbitMQ事务和Confirm发送方消息确认

生产者消息丢失,有没有办法可以解决这个问题?

RabbitMQ有两种方式来解决这个问题:

1.通过AMQP提供的事务机制实现;
2.使用发送者确认模式实现;

事务使用

事务的实现主要是对信道(Channel)的设置,主要的方法有三个:
channel.txSelect()声明启动事务模式;
channel.txComment()提交事务;
channel.txRollback()回滚事务;

Confirm发送方确认模式

Confirm发送方确认模式使用和事务类似,也是通过设置Channel进行发送方确认的.

Confirm的三种实现方式:
方式一:channel.waitForConfirms()普通发送方确认模式;
方式二:channel.waitForConfirmsOrDie()批量确认模式;
方式三:channel.addConfirmListener()异步监听发送方确认模式;

集群

一、为什么使用集群?
内建集群作为RabbitMQ最优秀的功能之一,它的作用有两个:

允许消费者和生产者在Rabbit节点崩溃的情况下继续运行;
通过增加节点来扩展Rabbit处理更多的消息,承载更多的业务量;

二、集群的特点

RabbitMQ的集群是由多个节点组成的,但我们发现不是每个节点都有所有队列的完全拷贝.

RabbitMQ节点不完全拷贝特性

为什么默认情况下RabbitMQ不将所有队列内容和状态复制到所有节点?

有两个原因:

  • 存储空间——如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据.
  • 性能——如果消息的发布需安全拷贝到每一个集群节点,那么新增节点对网络和磁盘负载都会有增加,这样违背了建立集群的初衷,新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟. 所以其他非所有者节点只知道队列的元数据,和指向该队列节点的指针.

三、集群异常处理

根据节点不无安全拷贝的特性,当集群节点崩溃时,该节点队列和关联的绑定就都丢失了,附加在该队列的消费者丢失了其订阅的信息,那么怎么处理这个问题呢?

这个问题要分为两种情况:
消息已经进行了持久化,那么当节点恢复,消息也恢复了;
消息未持久化,可以使用双活冗余队列,镜像队列保证消息的可靠性;

Kafka、RocketMQ、RabbitMQ都不能保证消息不重不丢(Exactly Once)

消息可靠性的服务水平:

  • At most once:至多一次,允许丢消息
  • At least once:至少一次,不允许丢消息,可以重复
  • Exactly once:恰好一次,不允许丢也不重复

questions

1.为什么用?

解耦:
异步:
削峰:

2.各种产品比较?

产品 开发语言 单机吞吐量 时效性 高可用 功能特性
RabbitMQ erlang 万级 us 高、分布式  
Kafka scala 10万级 ms 非常高、分布式  
RocketMQ java 10万级 ms 非常高、分布式  
ActiveMQ java 万级 ms 高、主从架构  

3.消息队列的优点和缺点?

可用性降低—-集群

系统变复杂—-

数据一致性问题—-最终一致性

4.如何保证消息队列的高可用?

rabbitMQ高可用

RocketMQ高可用—-双主双从

5.如何保证消息不丢失?

分析原因

1.生产者
2.MQ
3.消费者

解决

1.confirm

2.消息持久化

3.ack确认

6.保证消息不被重复消费?

原因

根本原因是网络不可达,不可避免

1.发送时消息重复

2.消费时消费重复

解决

保证消息消费业务的幂等

1.唯一id

2.消费者根据id查询是否消费

3.消费完毕写入redis/db

4.如果已经消费就丢弃

7.如何保证消息顺序消费?

1.是否理解消息的顺序消费

全局顺序消费、局部顺序消费

解决

一个消费者一个队列
MQ使用分段锁来保证单个Queue的有序消费

8.大量消息堆积如何处理?

原因:

1.消费者出现故障

2.消费了没有ack

解决

1.恢复消费者

2.写程序转发处理

9.消息过期?

原因

设置过期时间

过期消息可以转入死信队列

解决

1.启用专门消费者消费过期消息,记录日志

2.重新查询过期消息




本博客所有文章采用的授权方式为 自由转载-非商用-非衍生-保持署名 ,转载请务必注明出处,谢谢。
声明:
本博客欢迎转发,但请保留原作者信息!
博客地址:邱文奇(qiuwenqi)的博客;
内容系本人学习、研究和总结,如有雷同,实属荣幸!
阅读次数:

文章评论

comments powered by Disqus


章节列表