前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式基础概念-消息中间件[RabbitMQ]

分布式基础概念-消息中间件[RabbitMQ]

作者头像
@派大星
发布2023-11-30 17:01:34
1500
发布2023-11-30 17:01:34
举报
文章被收录于专栏:码上遇见你码上遇见你

消息队列的优缺点,使用场景

优点:

  1. 解耦,降低系统之间的依赖
  2. 异步处理,不需要同步等待
  3. 削峰填谷,将流量从高峰期引到低谷期进行处理

缺点:

  1. 增加了系统的复杂度,幂等、重复消费、消息丢失等问题的带入
  2. 系统可用性降低,mq的故障会影响系统可用
  3. 一致性,消费端可能失败

场景:

  • 日志采集、发布订阅等

如何保证消息不被重复消费

幂等:一个数据或者一个请求,重复来多次,确保对应的数据是不会改变的,不能出错。

思路

  • 如果是写redis,就没问题,反正每次都是set,天然幂等性
  • 生产者发送消息的时候带上一个全局唯一的id,消费者拿到消息后,先根据这个id去redis里查一下,之前有没消费过,没有消费过就处理,并且写入这个id到redis,如果消费过了,则不处理。
  • 基于数据库的唯一键

Kafka、ActiveMQ、RabbitMQ、RocketMQ对比

ActiveMQ:JMS规范,支持事务、支持XA协议,没有生产大规模支撑场景、官方维护越来越少

RabbitMQ:erlang语言开发、性能好、高并发,支持多种语言,社区、文档方面有优势,erlang语言不利于java程序员二次开发,依赖开源社区的维护和升级,需要学习AMQP协议、学习成本相对较高

以上吞吐量单机都在万级

Kafka:高性能,高可用,生产环境有大规模使用场景,单机容量有限(超过64个分区响应明显变 长)、社区更新慢。吞吐量单机百万

RocketMQ:Java实现,方便二次开发、设计参考了Kafka,高可用、高可靠,社区活跃度一般、支持语言较少。吞吐量单机十万

详细对比可参考文章:直击灵魂的面试之MQ七连问

RabbitMQ架构设计

Broker:RabbitMQ的服务节点

Queue:队列,是RabbitMQ的内部对象,用于存储消息。RabbitMQ中消息只能存储在队列中。生产者投递消息到队列,消费者从队列中获取消息并消费。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(轮询)给多个消费者进行消费,而不是每个消费者都收到所有的消息进行消费。(注意:RabbitMQ不支持队列层面的广播消费,如果需要广播消费,可以采用一个交换器通过路由Key绑定多个队列,由多个消费者来订阅这些队列的方式。

Exchange:交换器。生产者将消息发送到Exchange,由交换器将消息路由到一个或多个队列中。如果路由不到,或返回给生产者,或直接丢弃,或做其它处理。

RoutingKey:路由Key。生产者将消息发送给交换器的时候,一般会指定一个RoutingKey,用来指定这个消息的路由规则。这个路由Key需要与交换器类型和绑定键(BindingKey)联合使用才能最终生效。在交换器类型和绑定键固定的情况下,生产者可以在发送消息给交换器时通过指定RoutingKey来决定消息流向哪里。

bindingKey:通过绑定将交换器和队列关联起来,在绑定的时候一般会指定一个绑定键,这样RabbitMQ就可以指定如何正确的路由到队列了。

交换器和队列实际上是多对多关系。就像关系数据库中的两张表。他们通过BindingKey做关联(多对多关系表)。在投递消息时,可以通过Exchange和RoutingKey(对应BindingKey)就可以找到相对应的队列。

信道:信道是建立在Connection之上的虚拟连接。当应用程序与Rabbit Broker建立TCP连接的时候,客户端紧接着可以创建一个AMQP信道(Channel),每个信道都会被指派一个唯一的D。RabbitMQ处理的每条AMQP指令都是通过信道完成的。信道就像电缆里的光纤束。一条电缆内含有许多光纤束,允许所有的连接通过多条光线束进行传输和接收。

vhost:虚拟主机,每一个应用可以指定不同的vhost,此时对于应用来说、vhost就是broker

image.png

简述RabbitMQ的交换机类型

交换器分发会先找出绑定的队列,然后再判断routekey,来决定是否将消息分发到某一个队列中。

Channel channel=connection.createChannel();//在RabbitMQ中创建一个信 channel.exchangeDeclare("exchangeName","direct");//创建一个type为direct的交换器 channel.queueDeclare("queueName");//创建一个队列 channel.queueBind("queueName","exchangeName","zhangsna");//绑定并设置路由键 channel.queueBind("queueName","exchangeName","lisi");//绑定并设置路由键 channel.queueBind("queueName","exchangeName","wangwu");//绑定并设置路由键

fanout:扇形交换机,不再判断routekey,直接将消息分发到所有绑定的队列

direct:判断routekey的规则是完全匹配模式,即发送消息时指定的routekey要等于绑定的routekey

topic:判断routekey的规则是模糊匹配模式

header:绑定队列与交换器的时候指定一个键值对,当交换器在分发消息的时候会先解开消息体里的headers数据,然后判断里面是否有所设置的键值对,如果发现匹配成功,才将消息分发到队列中;这种交换器类型在性能上相对来说较差,在实际工作中很少会用到

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-11-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上遇见你 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 消息队列的优缺点,使用场景
  • 如何保证消息不被重复消费
  • Kafka、ActiveMQ、RabbitMQ、RocketMQ对比
  • RabbitMQ架构设计
  • 简述RabbitMQ的交换机类型
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档