Rabbitmq(2023-03-12 21:36)

文章详细介绍了如何在Docker中安装和启动Rabbitmq,强调了消息中间件的作用,如解耦、持久化、扩展性和削峰。此外,讨论了RabbitMQ的队列特性,交换机的fanout、direct、topic和headers四种类型,以及如何保证消息不丢失,包括持久化设置和确认机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Docker搭建Rabbitmq

Docker安装Rabbitmq超详细教程
docker中安装并启动rabbitMQ
docker run --name rabbitmq -d -p 15672:15672 -p 5672:5672 -v /usr/local/rabbitmq:/var/lib/rabbitmq rabbitmq:management
最后测试持久化成功的
docker run --name rabbitmq --hostname rabbitmq -d -p 15672:15672 -p 5672:5672 -v /usr/local/rabbitmq:/var/lib/rabbitmq rabbitmq:management
需要指定hostname,因为持久化的数据和hostname有关
rabbitmq 如何在 docker 下做数据持久化?
【Rabbitmq使用】docker compose 命令重启rabbitmq后数据丢失问题
k8s持久化存储rabbitmq数据

消息中间件的作用

解耦:在项目启动之初来预测将来会碰到什么需求是极其困难的。消息中间件在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,这允许你独立地扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束即可。

持久化:有些情况下,处理数据的过程会失败。消息中间件可以把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。在把一个消息从消息中间件中删除之前,需要你的处理系统明确地指出该消息已经被处理完成,从而确保你的数据被安全地保存直到你使用完毕。

扩展性:因为消息中间件解耦了应用的处理过程,所以提高消息入队和处理的效率是很容易的,只要另外增加处理过程即可,不需要改变代码,也不需要调节参数。

削峰:在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果以能处理这类峰值为标准而投入资源,无疑是巨大的浪费。使用消息中间件能够使关键组件支撑突发访问压力,不会因为突发的超负荷请求而完全崩溃。

可恢复性:当系统一部分组件失效时,不会影响到整个系统。消息中间件降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入消息中间件中的消息仍然可以在系统恢复后进行处理。
顺序保证:在大多数使用场景下,数据处理的顺序很重要,大部分消息中间件支持一定程度上的顺序性。
什么queue?queue就是一个顺序的,不管是先进先出,还是先进后出,queue就是一个有顺序的存在,rabbitmq也是如此,你先放进去的消息,肯定会被先消费出来,但是有一个关键的前提,只有一个消费者。

RabbitMQ中消息都只能存储在队列中,这一点和Kafka这种消息中间件相反。Kafka将消息存储在topic(主题)这个逻辑层面,而相对应的队列逻辑只是topic实际存储文件中的位移标识。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin,即轮询)给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。

交换机类型

RabbitMQ常用的交换器类型有fanout、direct、topic、headers这四种。

fanout

它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中. 在fanout模式下,无论你传输的routingkey是啥,都不会影响他的消息转发,因为fanout压根儿 就不考虑 bindingkey。真正的exchange消息转发路径,其实是bindingkey作用的。
fanout有人用吗,有,不多。这是一种傻瓜式的使用方式,只要有queue绑定到exchange,就能被转发,对于简单的业务系统,我们推荐使用fanout(不用进行routingkey和bindingkey的对应判断)。

direct

类型的交换器路由规则也很简单,它会把消息路由到那些BindingKey和RoutingKey完全匹配的队列中。
生产者提供routingkey,rabbitmq的exchange找到与routingkey对应的bindingkey,然后找到bindingkey指向的队列,将消息转发到这个队列。
direct有人用吗,有,不少。direct比fanout好在哪里,好在我们稍微的对queue有了一定的控制权。我们至少知道我们需要把消息路由到哪里。比如,我们目前有两种数据,一种数据是日志数据,一种是订单数据,我们需要日志数据发送到日志queue,把订单数据发送到订单queue。这时候你不能使用fanout。用direct,让我们创建不同的routingkey和bindingkey,日志绑定 日志queue,订单绑定订单queue。是不是觉得direct类型更加实用一些了?

topic

前面讲到direct类型的交换器路由规则是完全匹配BindingKey和RoutingKey,但是这种严格的匹配方式在很多情况下不能满足实际业务的需求。topic类型的交换器在匹配规则上进行了扩展,它与direct类型的交换器相似,也是将消息路由到BindingKey和RoutingKey相匹配的队列中,但这里的匹配规则有些不同,它约定:

  • RoutingKey为一个点号“.”分隔的字符串(被点号“.”分隔开的每一段独立的字符串称为一个单词),如 “com.rabbitmq.client”、“java.util.concurrent”、“com.hidden.client”;
  • BindingKey和RoutingKey一样也是点号“.”分隔的字符串;
  • BindingKey中可以存在两种特殊字符串“*”和“#”,用于做模糊匹配,其中星号用于匹配一个单词,“#”用于匹配多规格单词(可以是零个)

有啊,你搞个正则表达式啊。normal.# 开头的就是正常日志的queue。error.#就是错误的日志。direct能够完全替代topic,但是我们需要创建多个key绑定。topic也可以完全替代direct,而且topic比direct更加灵活。

topic和direct选择问题上,如果业务线单一,就搞direct就行了,就是制定专门的 RoutingKey 和 BindingKey;如果业务复杂,我们可以考虑topic,减少 RoutingKey 和 BindingKey的对应。

headers

headers类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。在绑定队列和交换器时制定一组键值对,当发送消息到交换器时,RabbitMQ会获取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。

我们有 string类型的routingkey进行bindingkey的对应,我疯了我是用 键值对,还得搞到 header里。几乎没有人使用。

如何保证消息不丢失

  1. RabbitMq需要进行我们一个持久化设置(durable)-- 细节的说明。他能够将我们未处理的消息进行磁盘持久化,保证我们消息不丢失。

  2. 保证生产者发送到RabbitMq的exchange里边是成功的,我们需要实用我们exchange接收消息的confirm机制。callback机制,confirmCallback。-- 细节的说明

  3. 保证消息能够成功的从exchange里路由到我们的queue中。消息在进入queue之前,需要我们进行路由,这个阶段要确保消息能够成功投递到我们的queue里,这个阶段,持久化特性是管不到的。还是回调机制,returnListener里边能够监听未正确路由到queue的消息。-- 细节的说明

  4. 保证消费者能够在接收到消息之后,进行消息的成功处理,并返回ack信息。–引申的面试题和细节。消费端,建议使用手动ack机制,就是通过代码进行我们ack,而不是使用rabbitmq的自动ack机制。

  5. 镜像队列。只要是单机的队列,再出现单点故障的时候,保不齐会丢失数据,镜像队列能够帮我们进行更加严密的数据保护。-- 细节的说明

1.持久化设置

  1. 持久化 exchange 交换机 持久化的交换机的元数据,能够提取我们的bindingkey(根据routingkey找到bindingkey的对应)

  2. 持久化 queue。如果我们的queue持久化了,而消息没有进行持久化,当我们的queue挂掉的时候,消息依然会丢失,我们此处queue的持久化,持久的内容是queue的元数据以及数据相关存储位置指针。

  3. 持久化我们的消息。 才会将我们的消息真正的写到磁盘上。 如果我们对每条消息都进行持久化的话,会造成一定程度的性能问题。不想消息丢失,就要进行持久化,所以在业务需求过程中, 我们需要权衡性能和业务数据的重要程度。(补救措施,新的面试题。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值