黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 Java學習 Java冪等控制的實現

Java冪等控制的實現

更新時間:2022-11-11 10:44:53 來源:動力節點 瀏覽1535次

簡單來說冪等保證了只要調用接口方法成功,外部多次調用對系統的影響是一致的,也就是一個請求多次重試的問題。

需要考慮冪等的場景:

客戶端存在多次提交或者超時重試的情況;

分布式架構中因網絡波動采用重試機制,如Dubbo的重試機制;

消息推送重試,如MQ重試;

不冪等帶來的影響:比如在支付場景下,消費者消費扣款消息,對一筆訂單進行扣款操作,該扣款操作需要扣除100元,在不冪等的情況下,如果消費者多次發起請求,就會造成多次扣款。

冪等性問題解決方案

冪等問題演示:

執行如下SQL,初始化金額為100;

create table order_pay
(
id int default 0 not null
primary key,
amt decimal(9, 2) default 0.00 null comment '金額',
status int null comment '狀態:0已完成/1處理中'
)comment '訂單支付表';
INSERT INTO test.order_pak (id, amt, status) VALUES (1, 100.00, 0);

pay接口:

@RestController
@RequestMapping("/test/order-pay")
public class OrderPayController {
@Autowired
IOrderPayService orderPayService;
@ApiOperation(httpMethod = "POST", value = "冪等性測試")
@PostMapping("pay")
public Resp pay(@RequestBody Req req) {
PayReq payReq = req.getData();
OrderPay order = orderPayService.getOne(new LambdaQueryWrapper().eq(OrderPay::getId, payReq.getBizId()));
order.setAmt(order.getAmt().subtract(payReq.getAmt()));
orderPayService.updateById(order);
return Resp.success("剩余金額更新為"+order.getAmt());
}
}

在不控制冪等的情況下,對pay接口連續發起5次請求,每一次扣減金額為10.00:

可以看到最后剩余金額更新為50 .00,我們發起一次請求,應該只扣除10.00,當遇到網絡重復或系統bug在不控制冪等的情況下會導致系統進行了多次扣款。那如何進行冪等控制呢?有什么方法呢?

冪等性的實現

保證冪等性的措施包括但不限于:

1.表單提交后按鈕置灰

限制客戶端請求

2.添加唯一索引

把唯一標識作為唯一索引,在重復創建時會拋出唯一約束異常

3.全局唯一ID

針對業務操作和內容生產全局唯一ID,在執行操作時判斷ID是否存在來判斷是否已執行

4.一鎖二查三更新

如果在流程處理過程中,業務要求不能并發執行,可以在流程執行之前根據業務ID獲取鎖,其他流程執行時獲取鎖就會失敗,也就是同一時間該流程只能有一個能執行成功,執行完成后,釋放鎖,同時也需要在入口處增加業務狀態的判斷,以避免對請求的多次處理。這種方式不止可用于冪等的控制,也可以防止并發操作帶來的異常。

@ApiOperation(httpMethod = "POST", value = "冪等性測試")
@PostMapping("pay")
public Resp pay(@RequestBody Req req) throws Exception {
PayReq payReq = req.getData();
// 獲取分布式鎖
redisTools.lock(payReq.getBizId().toString());
OrderPay order = orderPayService.getOne(new LambdaQueryWrapper().eq(OrderPay::getId, payReq.getBizId()));
if (order.getStatus()==1){
order.setAmt(order.getAmt().subtract(payReq.getAmt()));
order.setStatus(0);
orderPayService.updateById(order);
}
// 釋防鎖
redisTools.unlock(payReq.getBizId().toString());
return Resp.success("剩余金額為"+order.getAmt());
}

以下是對pay接口進行并發請求5次的結果:

可以看到,只有1個請求可以請求成功,另外4個請求在 redisTools.lock(payReq.getBizId().toString())獲取分布式鎖的步驟中拋出異常。

不加鎖與加鎖的區別

如果把分布式鎖的步驟去掉會發生什么樣的情況呢?

@ApiOperation(httpMethod = "POST", value = "冪等性測試")
@PostMapping("pay")
public Resp pay(@RequestBody Req req) throws Exception {
PayReq payReq = req.getData();
OrderPay order = orderPayService.getOne(new LambdaQueryWrapper().eq(OrderPay::getId, payReq.getBizId()));
if (order.getStatus()==1){
order.setAmt(order.getAmt().subtract(payReq.getAmt()));
order.setStatus(0);
orderPayService.updateById(order);
}
return Resp.success("剩余金額為"+order.getAmt());
}

依舊對pay接口進行并發請求5次,查看日志:

5次請求都成功了,但是邏輯執行了5遍,在復雜的業務流程下可能會引發其他不必要問題。

以上就是關于“Java冪等控制的實現”介紹,大家如果對此比較感興趣,想了解更多相關知識,不妨來關注一下本站的Java視頻教程,里面的課程內容從入門到精通,細致全面,通俗易懂,很適合小白學習,希望對大家能夠有所幫助哦。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 亚洲欧洲日产国码二区首页 | 人人做人人爽人人爱 | 黄色毛片免费进入 | 苗族一级特黄a大片 | 天天综合天天看夜夜添狠狠玩 | 国内外成人免费视频 | 又黄又爽的视频免费看 | 欧美精品免费专区在线观看 | 亚洲手机看片 | 黄色一级网 | 欧美日韩精品在线视频 | 日韩午夜高清福利片在线观看 | 亚洲欧美日韩精品久久亚洲区色播 | 色在线免费视频 | 欧美成人小视频 | 永久在线免费观看 | 美女视频黄的免费视频网页 | 91久久精品都在这里 | 可以直接看的av网址站 | 一级做性色a爰片久久毛片免费 | 国产高清美女一级a毛片久久w | 一级毛片a女人刺激视频免费 | 亚洲欧洲日产国码久在线观看 | 殴美一级毛片 | 国产精品七七在线播放 | 中文字幕第一页在线视频 | 色天天综合网色鬼综合 | 午夜视频网址 | 日韩精品一区二区三区在线观看 | 黄色一级大片 | 久久大香香蕉国产免费网站 | 久久香蕉精品视频 | 国产一区二区精品在线观看 | 高h猛烈做哭bl壮汉受欧美 | 2020国产精品视频免费 | 婷婷亚洲久悠悠色悠在线播放 | 欧美精品一二三区 | 欧美一级专区免费大片 | 亚洲精品香蕉婷婷在线观看 | 国产无限免费观看黄网站 | 亚洲国产精品日韩高清秒播 |