mybaits缓存引发的bug~

首先无力吐槽到了新公司的遭遇,来了俩月改了俩月bug,真是生活不息bug不止~

 

遇到的问题:

1.在做组合支付成功后,微信回调成功会触发给用户发送两条付款消息;结果每次都会余额支付一次,微信付款会连发两条一样的消息,让用户和我们都很慌好不好~

排查问题:

1.开始认为是不是回调失败重试机制引起的?但是看了下做了幂等了,不会出现重复消费和发送;

2.是不是微信抽了,然后观察是有规律的,只要组合支付涉及余额加微信,就重复发消息;

解决问题:

1.首先直接治标不治本的方式,排查到了发送人名单,在第二次发送微信支付时存在重复openid,所以做了去重,简单粗暴

criteria.setToUser(criteria.getToUser() == null ? null : criteria.getToUser().parallelStream().filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList()));

2.但是为啥会出现问题呢?还原前同事的神代码:

        //组合支付则循环两遍
        for (InsPayLogEntity entity : list) {
            //幂等性验证略...
            //构建发送的消息
            PayMsgCriteria payMsgCriteria = this.builtPayMsg(entity.getStoreCode(),
                    entity.getPayType(),
                    entity.getPayTarget(),
                    entity.getChangeAmount(),
                    entity.getReceiptTime(), entity.getPaySn());
            // 发送支付通知
            pushWeChatMpMsgService.asyncSendPayMsg(payMsgCriteria);
        }

        //构建信息方法
private PayMsgCriteria builtPayMsg(String storeCode, Integer payType, Integer payTarget, BigDecimal changeAmount, Date receiptTime, String paySn) {
        PayMsgCriteria criteria = new PayMsgCriteria();
        // 构建信息接收人
        //问题就在这里
        List<String> result = this.getSalesOpenIdList(storeCode);
        List<String> managerOpenIdList = this.getManagerOpenIdList();
        result.addAll(managerOpenIdList);
     
        criteria.setToUser(result);
   
        return criteria;
    }
    
    //获取门店用户openid
     private List<String> getSalesOpenIdList(String storeCode) {
        List<String> phoneList = userSalesService.selectPhoneList(storeCode);
        if (CollectionUtils.isEmpty(phoneList)) {
            return new ArrayList<>();
        }
        List<String> list = doorUserService.selectMpOpenId(phoneList);
        return list;
    }

debug发现,第二次循环后,result的数量从2变为29了~

正常来说应该每次查询数据库都是2才对,因为入参没变sql查询没变,这个29是addAll后面的集合后得到的;

 

3.查看日志找到问题了:

Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@63c163e1] from current transaction
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@63c163e1]

第一次循环查询了数据库,第二次则直接用的缓存,找到问题就好办了...

@原因就是我外面使用了@Transactional,开启事务后查询数据库会用同一个session,如果重复查询不变,会出现后面使用到一级缓存的情况~当然涉及到事务隔离级别,我的是Read committed,.所以出现更新列时缓存会失效,这里不多说~

 

4.修改代码:

        List<String> result = this.getSalesOpenIdList(storeCode);
        List<String> managerOpenIdList = this.getManagerOpenIdList();
        List<String> add = new ArrayList<>();
        add.addAll(result);
        add.addAll(managerOpenIdList);

这样第二次循环后,虽然用缓存,但是不会出现叠加重复的情况了~

 

5.避免缓存问题

  1. 在mybatis配置文件中localCacheScope=STATEMENT

  2. 在mapper配置文件中,给select设置flushCache=true。需要注意的是,这样会将local cache和cache都清空掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值