RabbitMq怎么防止交换机、队列和消息都设置了持久化但消息仍然丢失的问题

情景一:

消费者订阅消费队列时,autoAck(自动确认)参数设置了true,当消费者接收到了消息自动确认了,但是消息还没来得及处理,就宕机了。

解决方法:

autoAck参数设置成false,然后消费者处理完之后,手动确认

 

情景二:

在持久化消息的时候,数据在操作系统缓存中,还没写入磁盘中时宕机。

解决方法:

这里需要引入RabbitMq的镜像队列机制,相当于配置了副本,如果主节点(master)发生了宕机,可以自动切换到从节点(slave),这样可以有效的保证了高可用性,除非整个集群挂掉。虽然这种方式不能完全保证消息不丢失,但是比没有引入此机制可靠性会高出很多。

 

情景三:

生产者把消息发出去后,没有到达RabbitMq服务器

解决方法:

  • RabbitMq事务机制

RabbitMq客户端中与事务机制有关的方法有三个:channel.txSelect(将当前信道设置成事务信道)、channel.txCommit(提交事务)、channel.txRollback(回滚事务;当程序抛出异常时,catch到异常,调用方法)

提交事务:

        channel.txSelect();
        channel.basicPublish(EXCHANGE_NAME,ROUTING_KEY,null,"TEST".getBytes("UTF-8"));
        channel.txCommit();

AMQP协议流转过程:

1、客户端发送Tx.Select,将信道设置成事务模式

2、Broker回复Tx.Select-OK,确认将信道设置成事务模式

3、客户端发送消息

4、客户端发送完消息之后,发送Tx.Commit提交事务

5、Broker回复Tx.Commit-OK,确认事务已提交

事务回滚:

        try{
            channel.txSelect();
            channel.basicPublish("",QUEUE_NAME_TWO,false,properties,"TEST".getBytes("UTF-                8"));    
            throw new RuntimeException();
        }catch (Throwable throwable){
            channel.txRollback();
        }

AMQP协议流转过程:

1、客户端发送Tx.Select,将信道设置成事务模式

2、Broker回复Tx.Select-OK,确认将信道设置成事务模式

3、客户端发送消息

4、客户端发送Tx.Rollback,通知服务器回滚事务

5、Broker回复Tx.Rollback-OK,确认事务已回滚

 

如果发送多条消息,将channel.basicPublish、channel.txCommit、channel.txRollback方法放在同一个循环体内

        channel.txSelect();
        for (int i = 0;i < 100000; i++){
            try {
                channel.basicPublish("",QUEUE_NAME_TWO,false,properties,"TEST".getBytes("UTF-8"));
                channel.txCommit();
            }catch (Throwable throwable){
                channel.txRollback();
            }
        }

 

缺点:消耗服务器性能、严重降低RabbitMq的消息吞吐量

  • 通过发送方确认(publisher confirm)机制实现

生产者先将一个信道设置成confirm信道,这条信道上的消息都会被指定一个唯一ID(从1开始),当消息到达指定队列后,RabbitMq会返回一个确认(Basic.Ack)给生产者,如果消息或队列指定了持久化,则消息在写入磁盘后才会返回确认

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ 中,新建交换机队列和绑定它们之间的关系非常简单。 首先,需要连接到 RabbitMQ 服务器,并创建一个通道: ```python import pika # 连接到 RabbitMQ 服务器 connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() ``` 然后,可以使用 `channel.exchange_declare()` 方法创建一个新的交换机。该方法有四个参数: - `exchange`: 交换机名称 - `exchange_type`: 交换机类型,可以是 `direct`、`fanout`、`topic` 或 `headers` - `durable`: 是否持久,如果为 `True`,则交换机会在 RabbitMQ 服务器重启后仍然存在 - `auto_delete`: 是否自动删除,如果为 `True`,则交换机在不再被使用时会自动删除 例如,创建一个名为 `my_exchange` 的 `fanout` 类型的交换机,可以使用以下代码: ```python channel.exchange_declare(exchange='my_exchange', exchange_type='fanout', durable=True, auto_delete=False) ``` 接下来,可以使用 `channel.queue_declare()` 方法创建一个新的队列。该方法有三个参数: - `queue`: 队列名称,如果未指定,则会自动生成一个随机名称的队列 - `durable`: 是否持久,如果为 `True`,则队列会在 RabbitMQ 服务器重启后仍然存在 - `auto_delete`: 是否自动删除,如果为 `True`,则队列在不再被使用时会自动删除 例如,创建一个名为 `my_queue` 的队列,可以使用以下代码: ```python channel.queue_declare(queue='my_queue', durable=True, auto_delete=False) ``` 最后,可以使用 `channel.queue_bind()` 方法将交换机队列绑定在一起。该方法有三个参数: - `queue`: 队列名称 - `exchange`: 交换机名称 - `routing_key`: 路由键,用于将消息发送到特定的队列。对于 `fanout` 类型的交换机,该参数可以为空字符串。 例如,将名为 `my_queue` 的队列绑定到名为 `my_exchange` 的交换机上,可以使用以下代码: ```python channel.queue_bind(queue='my_queue', exchange='my_exchange', routing_key='') ``` 以上就是 RabbitMQ 中新建交换机队列和绑定它们之间关系的基本流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值