1.1 冪等性的概念
Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.
- 多次請求一個資源時,應該有相同的結果(網路超時等問題除外), 也就是說,一次請求被多次重復執行對資源自身的影響與第一次執行的影響相同,
- 例如:用戶查詢結果多次扣款, 流水記錄變成兩個就是沒有保證介面的冪等性,

1.2 防重設計和冪等設計
- 防重設計和冪等設計在很多情況下是可以通用的,解決方案也比較類似,區別在于:
- 防重設計:避免產生重復資料,對回傳結果沒有限制,
- 冪等設計:避免產生重復資料,要求每次請求都回傳同樣的結果,
1.3 常見場景
- FORM 表單,按鈕重復點擊,產生 ID 不一樣的兩條重復資料,
- 瀏覽器頁面回傳按鈕,此時資料依然存在,重復提交,
- 介面重試機制(超時問題),重試程序中會產生重復資料,
- 微服務呼叫,網路導致請求失敗,feign 觸發重復機制,
- MQ 同一條訊息重復讀取,
1.4 匯總分析(資料庫的角度)
- select 陳述句在資料不變的情況下,多次查詢的結果相同,天然冪等操作,
- insert 陳述句重復提交的情況下,會產生資料的重復,
- delete 陳述句一次或者多次結果都是洗掉資料(已洗掉的資料不存在,回傳0, 已洗掉的資料有多個,結果有多個, 洗掉操作也有乘方等屬性),
- update 陳述句在大多數場景中的結果相同,但增量修改需要乘方等保證,例如表中存在 version 欄位,此時更新時不是冪等,
1.5 保障冪等方式
1.5.1 唯一性索引
alter table xxx add UNIQUE KEY (key);
- 例外精準捕獲,以便回傳資料,
- DuplicateKeyException 例外,
- MySQLIntegrityConstraintViolationException 例外,
1.5.2 單獨表:防重復
- 核心:防重表和業務表必須在同一個事務中,
- 和唯一性索引的主要區別在于,并非所有的場景都不允許產生重復的資料,例如邏輯洗掉,
1.5.3 status 機制
- 根據影響行數來判斷是否更新成功,
update table set status = 1 where id = 1 and status=2;
1.5.4 資料庫悲觀鎖
select * from table id = 1;
select * from table id = 1 for update;
- 首先執行一遍查詢,如果此時不滿足條件,就直接回傳了,無需鎖住單條資料,
- 悲觀鎖之后,再進行邏輯判斷,
- 執行業務操作,
- 備注:mysql 存盤引擎選用 innodb ,悲觀鎖欄位最好是主鍵或唯一索引,不然可能會鎖表,
1.5.5 資料庫樂觀鎖(version )

select id,version,amount from table id = 1;
-- version 查詢結果為 0
update table set amount = amount + 1,version = version + 1
where id=1 and version = 0;
- 根據sql的執行結果影響行數判斷是否執行成功,
1.5.6 token機制
- 生成全域唯一的 token,token 放到 redis 中(注意設定過期時間),頁面跳轉時獲取 token ,
- 請求時攜帶token ,執行提交邏輯,

1.5.7 分布式鎖
- 通過 setNx、set 命令或者 Redission 第三方的框架,

1.6 小結
- 冪等不僅對一次(或多次)請求沒有副作用,對資源也沒有副作用, 例如,select 對資料庫不會產生任何影響,因為沒有被insert、update、delete,
- 網路超時等問題不在冪等討論范圍內,
- 冪等性是系統服務對外約定而不是實作的,約定如果介面呼叫成功,則外部多次呼叫對系統的影響是一致的, 宣告為冪等的服務,認為外部呼叫失敗是常態,失敗后一定會有重試,
更多精彩歡迎關注微信公眾號《格子衫007》!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/536838.html
標籤:其他
下一篇:python中回圈值的處理

