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

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

Java冪等控制的實現

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

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

需要考慮冪等的場景:

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

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

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

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 久色伊人 | 92国产福利久久青青草原 | 性xxx欧美| 国产一区亚洲二区 | 日本b站一卡二不卡 | 欧美成人免费在线视频 | 日韩欧美一区二区三区四区 | 在线97| 久久男人资源站 | 狠狠色丁香久久婷婷综合五月 | 精品午夜久久影视 | 色视频在线免费看 | 婷婷免费在线 | 国内精品免费久久久久妲己 | 欧美日韩视频在线第一区 | 久久精品国产精品亚洲艾 | 久草久草在线视频 | 日韩 亚洲 欧美 中文 高清 | 国产香蕉一区二区在线观看 | 日韩视频亚洲 | 2021国产精品系列一区二区 | 四虎www.| 国产91在线 | 欧美 | 国产精品免费福利 | www.黄网站 | 天天操夜 | 91免费福利视频 | 九九热观看视频 | 久久婷婷五夜综合色频 | 国产色婷婷亚洲 | 伊人五月 | 伊人影院在线观看视频 | 久青草国产在线视频亚瑟影视 | 色老头老太xxxxbbbb | 中文字幕亚洲综合精品一区 | 日韩国产欧美一区二区三区 | 久久综合九色综合欧洲 | 日本一级大黄毛片一级 | 奇米欧美成人综合影院 | 久久精品蜜芽亚洲国产a | 国产女人天堂 |