幂等性实现方案01

幂等性实现方案

一、什么是幂等性

所谓幂等性,简单地说,就是对接口的多次调用所产生的结果和调用一次是一致的。扩展一下,这里的接口,可以理解为对外发布的HTTP接口或者Thrift接口,也可以是接收消息的内部接口,甚至是一个内部方法或操作。

二、应用场景

支付业务

如上图所示用户下单后点击支付按钮进行支付。支付系统根据单号创建支付记录,然后调用银行接口,当一行扣款成功后,支付表修改支付状态为已支付。
但是,存在这样的情况,用户点击按钮无效,连续点击多次,是否会出现同一个订单支付多次?如何避免?这就是今天要讲的的幂等性。

作为对比,先看没有实现幂等性,也就是用户连续点击按钮,多次调用银行接口的情况。代码如下:

public void  payForOrder(String orderId){

        Order order = orderDao.findById(orderId);

        Payment payment = paymentDao.findPaymentByOrderId(orderId);

        payment.setOrderId(orderId);

        payment.setMoney(order.getMoney());

        payment.setPayStatus("0");//正在处理中

        paymentDao.update(payment);

        String flag = tranService.invoke(url,paymentId); //调用银行接口

        payment.setPayStatus(flag);

        paymentDao.update(payment);

}

有上面代码可知,当用户对一个单多次点击支付时,上面的代码一定会出现多次调用银行接口的情况。那么问题来了,如何保证幂等性?

介绍一个使用乐观锁实现幂等性的方案。通过新增版本号字段来实现。先看代码:

public payForOrder(String orderId){

        Order order = orderDao.findById(orderId);

        Payment payment = paymentDao.findPaymentByOrderId(orderId);

        boolean invokeInterface = false ;

        payment.setOrderId(orderId);

        payment.setMoney(order.getMoney());

        payment.setPayStatus("0");//正在处理中

        payment.setVersion(0);

        int records = paymentDao.updateByVersion(payment);

        if(records ){

                String flag = tranService.invoke(url,payment.getId()); //调用银行接口

                payment.setPayStatus(flag);   

                paymentDao.update(payment);

        }else{

                logger.error("重复调用............+orderId="+orderId);

        }

}

updateByVersion的模拟代码为:

 update  t_payment  set  orderId = #{orderId} , money=#{money},  payStatus=#{payStatus}  version=#{ version } +1 

    where id=#{id} and version=#{version}

用户第一次点击时 paymentDao.updateByVersion(payment) 的返回值为1 ,此时可以调用银行接口;当第二次点击时updateByVersion的返回值为 0 ,不会调用银行接口,实现了幂等性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值