大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

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

Java冪等控制的實現

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

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

需要考慮冪等的場景:

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

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

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

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 性欧美成人依依影院 | 青青草一区二区免费精品 | 亚洲久久草 | 久久久久久一级毛片免费无遮挡 | 男人深夜影院 | 国产一及片 | 乱子伦免费视频中文字幕 | 色哥网站 | 99中文在线 | 亚洲一级毛片欧美一级说乱 | 婷婷四房| 国产精品久久久久久久y | 狠狠干图片 | 狠狠躁夜夜躁人人爽天天3 狠狠躁夜夜躁人人爽天天miya | 国产精品剧情原创麻豆国产 | 亚洲国产欧美自拍 | 99九九成人免费视频精品 | 亚洲国产综合久久精品 | 成人亚洲网 | 久久久噜噜噜久久老司机 | 波多野结衣中文无毒不卡 | 欧美成人激情视频 | 午夜视频久久久久一区 | 四虎精品成人免费影视 | 日干夜操| 99干99| 久夜色精品国产一区二区三区 | 国产精品自在线拍国产 | 亚洲综合在线视频 | 四虎影视亚洲精品 | 欧美日韩国产在线人成 | 在线观看亚洲成人 | 伊人久久精品一区二区三区 | 欧美一级艳片爽快片 | 看全色黄大色黄大片色责看的 | 色综合久久六月婷婷中文字幕 | 欧美片欧美日韩国产综合片 | 18禁片一级毛片视频播放免费看 | 久久香蕉国产线看观看精品yw | 人人干夜夜操 | 国产在线91精品 |