冪等機(jī)制的核心是保證資源唯一性,例如客戶端重復(fù)提交或服務(wù)端的多次重試只會產(chǎn)生一份結(jié)果。支付場景、退款場景,涉及金錢的交易不能出現(xiàn)多次扣款等問題。事實上,查詢接口用于獲取資源,因為它只是查詢數(shù)據(jù)而不會影響到資源的變化,因此不管調(diào)用多少次接口,資源都不會改變,所以是它是冪等的。而新增接口是非冪等的,因為調(diào)用接口多次,它都將會產(chǎn)生資源的變化。因此,我們需要在出現(xiàn)重復(fù)提交時進(jìn)行冪等處理。
那么,如何保證冪等機(jī)制呢?事實上,我們有很多實現(xiàn)方案。其中,一種方案就是常見的創(chuàng)建唯一索引。在數(shù)據(jù)庫中針對我們需要約束的資源字段創(chuàng)建唯一索引,可以防止插入重復(fù)的數(shù)據(jù)。但是,遇到分庫分表的情況是,唯一索引也就不那么好使了,此時,我們可以先查詢一次數(shù)據(jù)庫,然后判斷是否約束的資源字段存在重復(fù),沒有的重復(fù)時再進(jìn)行插入操作。注意的是,為了避免并發(fā)場景,我們可以通過鎖機(jī)制,例如悲觀鎖與樂觀鎖保證數(shù)據(jù)的唯一性。這里,分布式鎖是一種經(jīng)常使用的方案,它通常情況下是一種悲觀鎖的實現(xiàn)。但是,很多人經(jīng)常把悲觀鎖、樂觀鎖、分布式鎖當(dāng)作冪等機(jī)制的解決方案,這個是不正確的。除此之外,我們還可以引入狀態(tài)機(jī),通過狀態(tài)機(jī)進(jìn)行狀態(tài)的約束以及狀態(tài)跳轉(zhuǎn),確保同一個業(yè)務(wù)的流程化執(zhí)行,從而實現(xiàn)數(shù)據(jù)冪等。
事實上,并不是所有的接口都要保證冪等,換句話說,是否需要冪等機(jī)制可以通過考量需不需要確保資源唯一性,例如行為日志可以不考慮冪等性。當(dāng)然,還有一種設(shè)計方案是接口不考慮冪等機(jī)制,而是在業(yè)務(wù)實現(xiàn)的時候通過業(yè)務(wù)層面來保證,例如允許存在多份數(shù)據(jù),但是在業(yè)務(wù)處理的時候獲取最新的版本進(jìn)行處理。