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 req ...
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》!