RabbitMQ解决分布式事务问题案例

配置类

/**
 * 商户金融权益分配rebbit配置
 */
@Configuration
public class ShopDelegateRabbitMqConfig {
    private static final Logger log = LoggerFactory.getLogger(ShopDelegateRabbitMqConfig.class);
    @Autowired
    private DelegateShopConfig delegateShopConfig;

    private String queueName;
    private String exchangeName;
    private String routingKey;

    @PostConstruct
    private void init() {
        String ip = getIp();
        if (ip.startsWith("17216")) {
            queueName = concatString(delegateShopConfig.getQueueName(), ip.replace(".", ""));
            exchangeName = concatString(delegateShopConfig.getExchangeName(), ip.replace(".", ""));
            routingKey = concatString(delegateShopConfig.getRoutingKey(), ip.replace(".", ""));
        } else {
            queueName = delegateShopConfig.getQueueName();
            exchangeName = delegateShopConfig.getExchangeName();
            routingKey = delegateShopConfig.getRoutingKey();
        }
        log.info("mq初始化信息完成,{},{},{}", queueName, exchangeName, routingKey);
    }

    private String getIp() {
        InetAddress ip = null;
        String localIp = "";
        try {
            ip = InetAddress.getLocalHost();
            localIp = ip.getHostAddress();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return localIp.replace(".", "");
    }

    private String concatString(String str, String ip) {

        return str + "_" + ip;
    }

    @Bean
    public Queue shopDelegateDelayQueue() {
        return new Queue(queueName);
    }
    /*@Bean
    public Queue shopDelegateDelayQueue() {
        return new Queue("shopDelegate_queue1");
    }*/

    @Bean
    public CustomExchange shopDelegateDelayExchange() {
        Map<String, Object> args = new HashMap<String, Object>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(exchangeName, "x-delayed-message", true, false, args);
    }

    @Bean
    public Binding bindingshopDelegateDelayNotify(@Qualifier("shopDelegateDelayQueue") Queue queue,
            @Qualifier("shopDelegateDelayExchange") CustomExchange customExchange) {
        return BindingBuilder.bind(queue).to(customExchange).with(routingKey).noargs();
    }

    public String getQueueName() {
        return queueName;
    }

    public void setQueueName(String queueName) {
        this.queueName = queueName;
    }

    public String getExchangeName() {
        return exchangeName;
    }

    public void setExchangeName(String exchangeName) {
        this.exchangeName = exchangeName;
    }

    public String getRoutingKey() {
        return routingKey;
    }

    public void setRoutingKey(String routingKey) {
        this.routingKey = routingKey;
    }
}

判断并入队

 @Override
    public Object autoDelegate(int shopId, int currentUserId) throws Exception {
        log.info("商户金融权益自动分配,商户ID:{}", shopId);
        // 获取金融权益数据,判断是否已分配
        Map<String, Object> shopDelegateInfo = shopDelegateMapper.findShopDelegateInfo(shopId);

        if (shopDelegateInfo != null && !shopDelegateInfo.isEmpty()
                && StringUtils.isNotBlank(ObjectUtils.toString(shopDelegateInfo.get("developidaft"), ""))) {
            log.info("商户金融权益已分配,禁止自动分配,商户ID:{}", shopId);
            return ResultDataUtils.failResult("商户已分配金融权益,禁止自动分配");
        }
        // 如果未分配,投递金融权益队列,自动分配

        Map<String, Object> params = new HashMap<>();
        params.put("shopId", shopId);
        rabbitTemplate.convertAndSend(shopDelegateRabbitMqConfig.getExchangeName(),
                shopDelegateRabbitMqConfig.getRoutingKey(), JSONObject.toJSONString(params));
        return ResultDataUtils.successResult("已开始自动分配,请稍后查询分配结果");
    }

监听并消费




@Component
public class ShopDelegateListener {
    private static Logger log = LoggerFactory.getLogger(ShopDelegateListener.class);

    private static final String delegateKey = "DELEGATE_";

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private DelegateShopMapper shopDelegateMapper;

    @Autowired
    private DelegateShopService shopDelegateService;
    @Autowired
    private DelegateShopConfig delegateShopConfig;
    @Autowired
    private ShopDelegateRabbitMqConfig shopDelegateRabbitMqConfig;

    /*@RabbitListener(queues = "shopDelegate_queue1")*/
    /*@RabbitListener(queues = "${delegate.queueName}")*/
    @RabbitListener(queues = "#{shopDelegateRabbitMqConfig.getQueueName()}")
    @RabbitHandler
    public void directMessage(String sendMessage, Channel channel, Message message) throws Exception {
        String shopId = "";
        long num = 0;
        try {
            // prefetchCount限制每个消费者在收到下一个确认回执前一次可以最大接受多少条消息,
            //通过basic.qos方法设置prefetch_count=1,这样RabbitMQ就会使得每个Consumer在同一个时间点最多处理一个Message
            channel.basicQos(1);
            log.info("接收到金融权益分配请求[{}]", sendMessage);

            JSONObject reqJson = JSONObject.parseObject(sendMessage);

            shopId = reqJson.getString("shopId");
            String redisKey = delegateKey + shopId;
            num = redisUtil.incr(redisKey, 1);
            redisUtil.expire(redisKey, 5 * 60);

            if (StringUtils.isBlank(sendMessage) || StringUtils.isBlank(shopId)) {
                log.info("权益分配请求参数为空!");
                return;
            }

            log.info("商户[{}]第[{}]次金融权益分配开始", shopId, num);

            // 调用金融权益分配请求
            shopDelegateService.shopDelegate(Integer.valueOf(shopId));
            // 确认消息已经消费成功
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            log.info("--" + sendMessage);
        } catch (Exception e) {

            log.error("商户[" + shopId + "]金融权益分配失败:", e);

            // 判断已投递次数是否超过最大限值
            if (isSend(shopId)) {
                //延时重新处理 ,延迟投递60秒
                log.info("商户[{}]第[{}]次金融权益分配失败,延迟投递60秒。。。", shopId, num);
                SendDelayMQ(sendMessage, 60 * 1000);
            } else {
                log.info("商户[{}]分配金融权益,已补偿超过限值,分配失败", shopId);
                shopDelegateMapper.updateDelegateStatus(shopId);
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        }
    }

    protected void SendDelayMQ(String orderNum, final Integer delay) {
        rabbitTemplate.convertAndSend(shopDelegateRabbitMqConfig.getExchangeName(),
                shopDelegateRabbitMqConfig.getRoutingKey(), orderNum, p -> {
                    p.getMessageProperties().setDelay(delay);
                    return p;
                });
    }

    /**
     * 判断是否继续投递 true 是 false 否
     * @param shopId
     * @return
     */
    private boolean isSend(String shopId) {
        // 分配失败,失败次数+1
        int num = shopDelegateMapper.updateSendNum(shopId);
        return num > 0 ? true : false;

    }
}

 	/**
     * 补偿轮询次数+1
     * @param shopId
     * @return
     */
    @Update("update wm_shop_dispatch_delegate set sendNum = sendNum +1 where shopId = #{shopId} and sendNum < limitNum")
    int updateSendNum(@Param("shopId") String shopId);
     /**
     * 更改分配金融权益失败
     * @param shopId
     * @return
     */
    @Update("update wm_shop_dispatch_delegate set status = 2 where shopId = #{shopId}")
    int updateDelegateStatus(@Param("shopId") String shopId);

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@淡 定

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值