RabbitMQ(二)

过期时间TTL

过期时间TTL表示可以对消息设置预期的时间,在这个时间内都可以被消费者接收获取;过了这个时间之后消息将自动被删除。

设置过期时间TTL的方式

在这里插入图片描述

1.可以在queue中设置
在这里插入图片描述

 @Bean
    public Queue directTtlQueue(){
        //设置过期时间
        Map<String, Object> args = new HashMap<>();
        //一定是设置一个int类型;如果是字符串会报错
        args.put("x-message-ttl",5000);
        return new Queue("ttl.direct.queue",true,false,false,args);
    }

在这里插入图片描述
2.在发送消息的时候配置
在这里插入图片描述

 /**
     *
     * @param userId
     * @param productId
     * @param num
     * ttl 发消息的时候设置ttl
     */
    public void makeOrderTtlMSg(String userId,String productId,int num){

        //1.根据商品id确认是否库存充足
        //2.保存订单
        String orderId = UUID.randomUUID().toString();
        System.out.println("订单生成成功:"+orderId);
        //3.通过消息队列来完成消息的分发
        /**
         * @param1 交换机
         * @param2 路由key/队列名
         * @param3 消息内容
         */
        String exchangeName = "ttl_direct_exchange";
        String routingkey = "ttlMsg";
        //给消息设置过期时间
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置过期时间,这里是字符串
                message.getMessageProperties().setExpiration("5000");
                message.getMessageProperties().setContentEncoding("UTF-8");
                return message;
            }
        };

        rabbitTemplate.convertAndSend(exchangeName,routingkey,orderId,messagePostProcessor);
    }

当两边均设置了过期时间以最小的过期时间为准,如queue设置的3s,发消息设置的是5s,则过期时间为3s

死信队列

DLX,全称为Dead-Letter-Exchange,可以称之为死信交换器,也有人称之为死信邮箱。当消息在一个队列中变成死信(dead message)之后,它能被重新被发送到另一个交换器中,这个交换器就是 DLX,绑定 DLX 的队列就称之为死信队列。

消息变成死信,可能由于以下的原因:

  • 消息被拒绝
  • 消息过期
  • 队列达到最大长度

##内存磁盘监控
一般内存设置为,自身内存的0.4 - 0.7,官网说的是设置在0.4~0.66之间

修改rabbitmq设置的内存

rabbitmqctl set_vm_memory_high_watermark < fraction>
rabbitmqctl set_vm_memory_high_watermark absolute 50MB

可在配置文件中配置 rabbitmq.conf

#默认
#vm_memory_high_watermark.relative = 0.4
#使用relative 相对值进行设置fraction建议数值在0.4到0.7之间,不超过0.7
vm_memory_high_watermark.relative = 0.6
#使用absolute的绝对值的方式,KB MB GB对应如下
vm_memory_high_watermark.absolute =2GB

内存换页

在RabbitMQ达到内存阈值并阻塞生产者之前,会尝试将内存中的消息换页到磁盘,以释放内存空间。内存换页由换页参数控制,默认为0.5,表示当内存使用量达到内存阈值的50%时会进行换页,也就是0.4*0.5=0.2。

vm_memory_high_watermark_paging_ratio=0.5

当换页阈值大于1时,相当于禁用了换页功能

集群

单机多实例搭建

1.一主多从

启动主节点

#停止应用
sudo rabbitmqctl -n rabbit-1 stop_app
#目的是清除节点上的历史数据(如不清楚 无法将节点加入到集群)
sudo rabbitmqctl -n rabbit-1 reset
#启动应用
sudo rabbitmqctl -n rabbit-1 start_app

绑定从节点

#如果是单独的机器@‘Server-node’,就是ip;或者虚拟映射ip的别名
sudo rabbitmqctl -n rabbit-2 join_cluster rabbit-1@‘Server-node’

#停止应用
sudo rabbitmqctl -n rabbit-2 stop_app
#目的是清除节点上的历史数据(如不清楚 无法将节点加入到集群)
sudo rabbitmqctl -n rabbit-2 reset
#将rabbit2节点加入到rabbit1(主节点)集群当中【server-node服务器的主机名】
#如果是单独的机器@'Server-node',就是ip;或者虚拟映射ip的别名
sudo rabbitmqctl -n rabbit-2 join_cluster rabbit-1@'Server-node'
#启动应用
sudo rabbitmqctl -n rabbit-2 start_app

验证集群状态

sudo rabbitmqctl cluster_status -n rabbit-1

主从集群里,任一个节点新加队列或交换机都会在所有节点中展示

当主节点从节点均挂掉时,先启从节点无法重启;
主节点挂掉后无法正常使用

#停止一个节点
rabbitmqctl -n rabbit-2 stop_app

分布式事务

在不同系统之前如何保证数据完整性的一种方案

分布式事务的方式

一、 两阶段提交(2PC)需要数据库厂商的支持,java组件有atomikos等

两阶段提交(Two-phase Commit,2PC)通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务。
存在的问题:
1.同步阻塞,所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作
2.单点问题,协调者在2PC中起到非常大的作用,发生故障将会造成很大的影响,特别是在阶段二发生故障,所有参与者会一直等待状态,无法完成其他操作
3.数据不一致,在阶段二,如果协调者只发送了部分Commit消息,此时网络发生异常,那么只有部分参与者接收到Commit消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
4.太过保守,任意一个节点失败就会导致整个事务失败,没有完善的容错机制。

二、补偿事务(TCC)严选、阿里、蚂蚁金服

TCC其实就是采用补偿机制,其核心思想是:针对每个操作,要注册一个与其对应的确认和补偿(撤销)操作,它分为三个阶段:

  • Try 阶段主要对业务系统做检测及资源预留
  • Confirm阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行Confirm阶段时,默认—Confirm阶段是不会出错的,即只要Try成功,Confirm一定成功
  • Cancel阶段主要是在Try执行错误,需要回滚状态下执行的业务取消,预留资源释放

优点:

比2PC实现以及流程相对简单一些,但数据的一致性比2PC也要差一些

缺点:
在2 、3步中可能失败,TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能不太好定义和处理。

三、本地消息表(异步确保)比如:支付宝、微信支付主动查询支付状态,对账单的形式

本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。

  • 分布式事务操作的一方完成业务数据操作之后,向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。
  • 之后将本地消息表中的消息转发到Kafka等消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。
  • 在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。
    优点:
    一种非常经典的实现,避免了分布式事务,实现了最终一致性。
    缺点:
    消息表会耦合到业务系统中,如果没有封装号的解决方案,会有很多杂活需要处理

TCC事务问题:
无论何种方式也无法完全避免,只能让更大比例数据一致

使用RabbitMQ消费消息失败可能出现的问题:

死循环一直重试消费,导致rabbitmq磁盘慢;

解决消息重试的几种方案:

1.控制重发的次数
2.try+catch+手动ack
3.try+catch +手动ack+死信队列+人工干预

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值