參考鏈接
引言
什么是冪等
摘自百度百科。
冪等(idempotent、idempotence)是一個數學與計算機學概念,常見於抽象代數中。
在編程中一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等函數,或冪等方法,是指可以使用相同參數重復執行,並能獲得相同結果的函數。這些函數不會影響系統狀態,也不用擔心重復執行會對系統造成改變。例如,“setTrue()”函數就是一個冪等函數,無論多次執行,其結果都是一樣的.更復雜的操作冪等保證是利用唯一交易號(流水號)實現。
冪等的作用
無論是單機或者分布式系統都會遇到並發的問題,除了使用類似流量控制等的方法之外,當請求真正到達后端服務器之后,冪等設計
就可以作為一種解決方案了。
基於消息隊列的分布式架構的系統中,由於各種原因,比如網絡波動等,隊列里面的消息就會重發,從本質上來說,系統自動產生了一個並發請求。簡單一點也可以理解為一個webapi接口被完全“相同”的參數調用了多次,這時候冪等就派上用處了。
看了一些文章,總結一下基本的手段。
具體方法
總的來說,冪等實現中關鍵的其實是防並發的問題。系統只要先防止並發問題,然后再根據唯一的業務主鍵返回對應的結果就好。
單機系統的lock()
.net的lock或者java的ReentrantLock等高級語言中都有關鍵字,基本的用法就是構造一個對象,對於關鍵的步驟,lock這個對象,然后執行業務代碼,操作完成再釋放。
去重表
我們在執行完所有的數據庫操作之后,往一張冗余表插入一條更新記錄,根據數據庫唯一主鍵,如果數據已經存在就會報錯,然后回滾操作。
Multiversion concurrency control
字面上理解就是多版本並發控制。是一種基於數據庫
的並發控制。我們可以讓關鍵的數據表多一個version字段。先獲取記錄值$oldVersion,然后更新的時候增加條件version=$oldVersion。用sql描述就是
select id, value1, version from table1 where id = $id; --version為$oldVersion
update table1 set value1=$newValue where id = $id and version = $oldVersion; -- 比原先id=$id 多一個version=$oldVersion條件。
這樣,代碼中就能通過判斷受影響的行數是否為1來判斷此次更新是否成功。
這屬於一種樂觀鎖的實現。所以,一般可以加上一些重試機制來優化用戶體驗。EFCore中的並發控制也是基於這種實現。
select for update 悲觀鎖
簡單來說鎖記錄,阻止其他進程更新記錄,或者是讀取記錄(需要設置隔離等級)。
詳細內容等下一篇總結mysql數據庫鎖相關的內容時再說。
先查后改
修改之前我們先查一下“記錄”是否存在,如果有,就直接返回,才執行操作。這個記錄可以是數據庫里面的,並發量大的時候不能用,因為會出現兩個進程都讀取到不存在的情況。這時候就需要通過redis等高速緩存來實現。因為本身redis是單線程的,所有可以保證同一時間只有一個進程獲取到。