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

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

Java冪等控制的實現

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

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

需要考慮冪等的場景:

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

分布式架構中因網絡波動采用重試機制,如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視頻教程,里面的課程內容從入門到精通,細致全面,通俗易懂,很適合小白學習,希望對大家能夠有所幫助哦。

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

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 2021天天躁狠狠燥 | 免费在线观看一级毛片 | 国产亚洲精品高清在线 | 天天射天天干 | 一级特黄录像绵费播放 | 日韩欧美中国a v | 又粗又黄又猛又爽大片免费 | 国产亚洲高清在线精品99 | 日韩在线1 | 成人超污免费网站在线看 | 激情五月情 | 国产在线播放一区二区 | www.午夜剧场| 欧日韩一区二区三区 | 一级免费黄色片 | 亚洲国产中文字幕 | 噜噜色综合噜噜色噜噜色 | 欧美一级级a在线观看 | 日韩欧美一区二区三区免费看 | 国产精品视_精品国产免费 国产精品视频a | 成年香蕉大黄美女美女 | 中文字幕视频二区 | 亚洲欧美日韩在线2020 | 欧美成人h精品网站 | 欧美色图综合 | 成人在线一区二区三区 | 999www成人 | 18视频在线观看网站 | 久久五月天婷婷 | 国产精品欧美日韩精品 | 日韩精品一区在线观看 | 日本人乱人乱亲乱色视频观看 | 中文字幕一区二区三区免费视频 | 2015日韩永久免费视频播放 | 黄色大片毛片 | 久久久久久88色偷偷 | 免费小视频网站 | 亚洲伊人成人网 | 日b在线 | 人人爽人人爽人人片c | 一级高清毛片免费a级高清毛片 |