java冪等性的控制

轉載:http://m.blog.csdn.net/loveblog1314/article/details/72649809

什麼是冪等性

抄用一段數學上的定義:f(f(x)) = f(x)。x被函數f做用一次和做用無限次的結果是同樣的。冪等性應用在軟件系統中,我把它簡單定義爲:某個函數或者某個接口使用相同參數調用一次或者無限次,其形成的後果是同樣的,在實際應用中通常針對於接口進行冪等性設計。舉個栗子,在系統中,調用方A調用系統B的接口進行用戶的扣費操做時,因爲網絡不穩定,A重試了N次該請求,那麼無論B是否接收到多少次請求,都應該保證只會扣除該用戶一次費用。java

加深對冪等性的瞭解

冪等性通常應用於協議設計,TCP協議支持冪等嗎?答案是確定的,在網絡不穩定時,操做系統能夠肆無忌憚的重發TCP報文片斷。TCP協議可以保證冪等的核心在於sequence number字段,一個序列號的在較長的一段時間內均不會出現重複。對於應用層的協議設計,原理和TCP是相似的,咱們須要一個不重複的序列號。再簡單一點說,在一個業務流程的處理中,咱們須要一個不重複的業務流水號,以保證冪等性。
舉個實際應用場景:用戶A在網頁上發起一筆遊戲充值請求,瀏覽器引導用戶去銀行支付,支付成功後系統給用戶進行充值。
協議設計上,咱們經過全局惟一的充值訂單號貫穿整個業務流程,使該業務支持冪等。
咱們先從一個簡單的程序理解一下冪等性:
public class Main {
    private int i = 0;
    
    //這個方法不具備冪等性,每調用一次,它就會改變Main的狀態(即改變了i)
    public void idempotent() {
        i++;
    }
    
    //冪等性,不管這個方法調用多少次,它都不會改變Main類的狀態。
    public void simple() {
        System.out.println(i);
    }
}
看完這些,你彷佛對冪等性有了更深的瞭解。那麼冪等性問題會出如今哪些場景呢?
電商,第三方支付,搶紅包等場景。
這些應用場景,你彷佛看到了他們的共同特徵。對,那就是高併發。

冪等控制的實現

HTTP的冪等性

冪等表示:請求服務器一次或是屢次,返回的結果均是同樣的【select 】通常是GET請求nginx

非冪等表示:請求服務器不一樣的次數,返回的結果將是不同的[update   delete] 通常是POST請求web

HTTP協議自己是一種面向資源的應用層協議,但對HTTP協議的使用實際上存在着兩種不一樣的方式:一種是restful,它把HTTP當成應用層協議,另外一種是SOA,它並無徹底把HTTP當成應用層協議,而是把HTTP協議做爲了傳輸層協議,而後在HTTP之上創建了本身的應用層協議。redis

restful風格,想了解的能夠去看看webservice編程,這裏不是本文的主題。數據庫

本文所討論的HTTP冪等性主要針對RESTful風格的,不過正如上一節所看到的那樣,冪等性並不屬於特定的協議,它是分佈式系統的一種特性;因此,不管是SOA仍是RESTful的Web API設計都應該考慮冪等性。編程

 

重要方法 安全 冪等
GET
POST
PUT
DELETE

 

數據庫冪等

數據庫上的冪等和事務是一體的。
1. 查詢操做 
查詢一次和查詢屢次,在數據不變的狀況下,查詢結果是同樣的。select是自然的冪等操做 
 2. 刪除操做 
刪除操做也是冪等的,刪除一次和屢次刪除都是把數據刪除。(注意可能返回結果不同,刪除的數據不存在,返回0,刪除的數據多條,返回結果多個) 
3.惟一索引,防止新增髒數據 
好比:支付寶的資金帳戶,支付寶也有用戶帳戶,每一個用戶只能有一個資金帳戶,怎麼防止給用戶建立資金帳戶多個,那麼給資金帳戶表中的用戶ID加惟一索引,因此一個用戶新增成功一個資金帳戶記錄 
4.悲觀鎖 
獲取數據的時候加鎖獲取 
select * from table_xxx where id='xxx' for update; 
注意:id字段必定是主鍵或者惟一索引,否則是鎖表,會死人的 
悲觀鎖使用時通常伴隨事務一塊兒使用,數據鎖定時間可能會很長,根據實際狀況選用 
5. 樂觀鎖 
樂觀鎖只是在更新數據那一刻鎖表,其餘時間不鎖表,因此相對於悲觀鎖,效率更高。

 

客戶端冪等控制機制-token

業務要求:  頁面的數據只能被點擊提交一次  發生緣由:  因爲重複點擊或者網絡重發,或者nginx重發等狀況會致使數據被重複提交  解決辦法:  集羣環境:採用token加redis(redis單線程的,處理須要排隊)  單JVM環境:採用token加redis或token加jvm內存  處理流程:  1. 數據提交前要向服務的申請token,token放到redis或jvm內存,token有效時間  2. 提交後後臺校驗token,同時刪除token,生成新的token返回  token特色:  要申請,一次有效性,能夠限流 
相關文章
相關標籤/搜索