因爲調用方爲了保證消息的發送是高可用的,因此會有重試機制。假若有這個場景:
服務A調用服務B,此時第一個請求,因爲網絡緣由,服務B延遲收到了這個請求,或者服務B回覆服務A的時候,服務A沒收到,致使服務A又發送了相同的請求。此時,服務B就又處理了一次請求,若是這個請求是對數據庫進行操做的,好比對金額的扣減,那這麻煩可大了。
首先,咱們先看看接口是否須要冪等性。如下兩個不須要保證冪等性:數據庫
基本上對數據庫的新增、修改、刪除都須要冪等性。網絡
新增的時候,惟一標識就是主鍵(分佈式下的主鍵是怎麼生成的?),因此儘管屢次插入,成功的只能一條數據,此時新增是冪等性的。若是此時主鍵是數據庫生成的,那須要惟一索引避免插入重複數據,這個時候也是冪等性的。若是既須要數據庫生成主鍵,也沒有惟一索引,那這個冪等就沒辦法保證了。因此要保證新增的冪等,必須本身生成主鍵(推薦),或者建立惟一索引。併發
修改分爲兩種狀況(這邊只考慮請求重試,不考慮併發的狀況,併發在分佈式鎖中討論),一個是直接賦值,一個是相對賦值。分佈式
# 直接賦值 update table set num=5 where id=1; # 相對賦值 update table set num=num-1 id=1;
若是是直接賦值的,無論給num賦值多少次5,結果仍是5,那若是是相對賦值的,此時就會一直減1。此時應該先從數據庫查詢出num,獲得結果爲5,服務A計算num-1,再把結果4傳給服務B,服務B無論執行多少次set num=4都同樣,這樣就是冪等的。spa
刪除也分兩種狀況,一個是指定值刪除,一個是範圍值刪除。3d
# 直接賦值 delete from table where id=1; # 相對賦值 delete from table order by id desc limit 3;
若是是指定值刪除,第一次刪除返回1,第二次刪除返回0,無論執行幾回,數據庫都沒有id=1的信息,因此是冪等的。
若是是範圍值刪除,第一次執行刪除3個,第二次執行又刪除3個,這樣就不是冪等的。方法跟上面相似,先把須要刪除的id查詢出來,獲得10,9,8,而後把須要刪除的id(10,9,8)傳給服務B,服務B無論刪除幾回id(10,9,8),數據庫都沒有id(10,9,8)的信息,也沒有額外多刪除其餘的信息,因此是冪等的。code