大战熟女丰满人妻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視頻教程,里面的課程內容從入門到精通,細致全面,通俗易懂,很適合小白學習,希望對大家能夠有所幫助哦。

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

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 欧美日本黄色片 | 夭天干夜夜怕 | 国产精品久久久久久五月尺 | 久久久久久久久久综合情日本 | 北岛玲日韩精品一区二区三区 | 免费国产福利 | 色人阁网站 | 在线成人精品国产区免费 | 不卡的中文字幕 | 日日噜噜夜夜狠视频免费 | 不卡高清av手机在线观看 | 精品国产品国语在线不卡丶 | 四虎国产精品永久在线播放 | 人做人爱视频欧美在线观看 | 99精品wwxx在线观看 | 日韩欧美视频一区二区在线观看 | 国产美女做爰免费视 | 国产成人亚洲综合欧美一部 | 欧美区日韩区 | 精品国产综合成人亚洲区 | 国产在热线精品视频国产一二 | 一级毛片一级片 | 日本高清一级片 | 国产亚洲精品97在线观看 | 操美女穴 | 88国产精品视频一区二区三区 | 女人18毛片a级毛片免费视频 | 国产欧美自拍 | 国产在线原创剧情麻豆 | 亚洲精品区 | 五月花激情网 | 久久永久免费中文字幕 | 欧美激情精品久久久久久不卡 | 久久精品国产99久久99久久久 | 国产大尺度福利视频在线观看 | 久久精品国产eeuss | 高清国产精品久久久久 | 成人精品视频在线观看播放 | 国产a不卡片精品免费观看 国产a高清 | 久久精品免看国产成 | 手机在线观看亚洲国产精品 |