RabbitMQ入门学习笔记1
关于RabbitMQ
- 出身:诞生于金融行业的消息队列
- 语言:Erlang
- 协议:AMQP(Advanced Message Queuing Protocol 高级消息队列协议)
- 关键字:内存队列,高可用
队列结构
- Producer/Consumer:生产者、消费者
- Exchange:交换器,可以理解为队列的路由逻辑,交换器主要有三种,上图中是Direct交换器
- Queue:队列
- Binding:绑定关系,实际是交换器上映射队列的规则
发送和消息一条消息
在上图的模式下,交换器的类型未Direct,伪代码表示消息的生产和消费
消息生产
#消息发送方法
#messageBody 消息体
#exchangeName 交换器名称
#routingKey 路由键
publishMsg(messageBody,exchangeName,routingKey){
......
}
#消息发送
publishMsg("This is a warning log","exchange","log.warning");
RoutingKey=log.warning,和队列A与交换器绑定在一起,所以消息会被路由到队列A上。
消息消费
对于消费消息而言,消费者直接指定要消费的队列即可,比如指定消费队列A的数据。
需要注意的是,在消费者消费完成数据后,返回给RabbitMQ ACK消息,RabbitMq会删掉队列中的该条信息。
多种消息路由模式
在Exchange这个模块上,RabbitMq主要支持了Direct、Fanout、Topic三种路由模式,RabbitMq在路由模式上下功夫,也说明了它在设计上想要满足多样化的需求。
Direct和Fanout模式比较好理解,类似于单播和广播模式,Topic模式比较有意思,它支持自定义匹配规则,按照规则把所有满足条件的消息路由到指定队列,能够帮助开发者灵活应对各类需求。
消息的存储
RabbitMQ的消息默认是保存在内存里的,实际上不光是消息,Exchange路由等信息实际都在内存中。内存的优点是高性能,问题在于故障后无法恢复,所以RabbitMq也支持持久化的存储,也就是写磁盘。
要在RabbitMQ中持久化消息,要同时满足三个条件:
1.消息投递时使用持久化投递模式
2.目标交换器是配置为持久化的
3.目标队列是配置为持久化的
RabbitMQ持久化消息的方式是常见的写日志方式:
1.当一条持久化消息发送到持久化的Exchange上时,RabbitMQ会在消息提交到日志文件后,才发送响应。
2.一旦这条消息被消费后,RabbitMQ会把日中中该条消息标记未等待垃圾收集,之后会从日志中清除。
3.如果出现故障,自动重建Exchange,Bindings和Queue,同时通过重播持久化日志来恢复消息。
消息投递模式
1.发后即忘
RabbitMQ默认发布消息是不会返回任何结果给生产者的,所以存在发送过程中丢失数据的风险。
2.AMQP事务
AMQP事务保证RabbitMQ不仅收到了消息,并成功将消息路由到了所有匹配的订阅队列,AMQP事务将使得生产者和RabbitMQ产生同步。
虽然事务使得生产者可以确定消息已经到达RabbitMQ中的对应队列,但是却会降低2-10倍的消息吞吐量,所以也是这个原因,事务用得会比较少。
3.发送发确认
开启发送方确认模式后,消息会有一个唯一的ID,一旦消息被投递给所有匹配的队列后,会回调给发送方应用程序(包含消息的唯一ID),使得生产者知道消息已经安全到达队列了。
如果消息和队列是配置成了持久化,这个确认消息只会在队列将消息写入磁盘后才会返回。如果RabbitMQ内部发生了错误导致这条消息丢失,那么RabbitMQ会发送一条nack消息,当然这个是不能保证的。
这种模式由于不存在事务的回滚,同时整体仍然是一个异步过程,所以更加轻量级,对服务器性能的影响很小,应用相对也较广泛。
疑问点:
1.rabbitmq队列有没有副本,消费者从一个队列获取消息时,可以并发同时进行获取吗,还是只能是先后顺序,队列内部数据实际是如何存储的?
2.rabbitmq消费过程中的channel通道是做复用吗,消费消息后,必须按照消费先后顺序进行ack消息吗,是否可以将channel和message交给线程池去多线程处理,然后分别进行ack呢?
3.rabbitm消息持久化的策略是怎么样的,又有着怎么样的容量管理和消息清除策略?