冪等和非冪等的區別

前兩天,在日常工作的接口測試中,發現了一個現象,點擊web頁面裏面表格顯示的一個查詢按鈕時,它的接口路徑還是沒變,當時感到奇怪,
一般情況下,在web頁面中,每一個可點擊的地方都有可能時一個新的接口,也就是一個新的url,至少url的後綴是會有變化的;今天還是頭一次碰到這種現象,而且是put請求的接口;
我就很納悶了,查詢接口一般都是get請求的,這裏爲什麼還用了put請求呢?後來在網上查了一下,原來是涉及到冪等的知識;所以今天咱就捋一捋這塊的知識點:
一、冪等的概念
冪等:多次重複操作和一次操作產生的影響是一樣的;
非冪等:多次重複操作和一次性操作產生的影響是不一樣的;
通俗點講:就是你調用的這個接口(前端的這個按鈕),後臺都返回同樣的數據,並且不會修改狀態信息,接口可重複調用,一次或者多次都是一樣的數據。
注意:這裏強調的是產生的影響是一樣的,而不是結果一樣。就拿最常見的增刪改查的業務,一個新增接口add;比如你一次插入請求插入一條數據,產生的影響是多一條記錄,
後臺業務層在沒有返回顯示新增成功之前;哪怕你多次插入請求產生的影響如果產生的影響也是多一條數據,那麼就是冪等的,而不是說一次插入的一條數據和多次插入的數據結果一樣。
二、什麼業務場景使用冪等性
2.1案例一:舉個最簡單的例子,就是平時的手機支付,用戶購買商品支付購買,支付扣款成功,但是返回結果的時候網絡異常,後臺那邊錢已經扣了,用戶並不知道,因爲網絡原因沒推送回來扣款成功的消息,
如果用戶再次點擊按鈕,平臺如果進行第二次扣款,且返回結果成功,用戶查詢餘額返發現多扣錢了,流水記錄也變成了兩條。這就不合理了;用戶明明只需要付一筆支付就行,
雖然動作執行了2次,但產生的影響是一樣的,即理論上只應該扣一次錢就行;這裏就要用到冪等;如果沒用冪等很有可能會造成扣款2次的情況發生。
2.2一般有以下幾種場景會用到:
①我們發起一筆付款請求,應該只扣用戶賬戶一次錢,當遇到網絡重發或系統bug重發,也應該只扣一次錢;
②發送消息,也應該只發一次,同樣的短信發給用戶,用戶會哭的;
③創建業務訂單,一次業務請求只能創建一個,創建多個就會出大問題等等很多重要的情況都需要冪等的特性來支持。
④火車票出票,購票成功,還在等待中,及時網絡異常,多次點擊,最終出來的還是一張票,不會出來很多張票。
由此可見:在設計系統時,冪等是首要考慮的問題,尤其是在像支付寶,銀行,互聯網金融公司等涉及的都是錢的系統,既要高效,數據也要準確,
所以不能出現多扣款,多打款等問題,會極度的影響用戶體驗,會被投訴,甚至會喫官司。
三、技術方面如何來實現冪等
1、可以通過http協議(超文本傳輸協議):來區分。get,put,delete是天然的冪等操作,所以在儘量使用這些方法。
冪等的:get、put、delete
非冪等的:post、patch
2、建立唯一索引,能防止新增的髒數據,比如在銀行的賬戶中,每個支付寶的資金賬戶,支付寶也有用戶賬戶,每個用戶只能有一個資金賬戶,怎麼防止給用戶創建銀行賬戶多個,那麼給賬戶表中的用戶ID加唯一索引,
所以一個用戶新增成功一個資金賬戶記錄。要點:唯一索引或唯一組合索引來防止新增數據存在髒數據(當表存在唯一索引,併發時新增報錯時,再查詢一次就可以了,數據應該已經存在了,返回結果即可)。
3、token + (redis) 的機制(token的特點 : 一次有效性,時效性,可以對流量進行控制),可以防止頁面的重複提交。具體實現 : 發生的原因由於重複的點擊 , 網絡原因導致了多次發送請求,
或者由於nginx重發等情況會導致數據被重複的提交 ; 解決的方案 :在數據提交給後臺服務器處理時,要向服務器申請token(全局唯一的變量),將token存放到redis(可以是其他的)中,設置token的有效時間。
當服務器接受到請求進行處理時,對token進行校驗,校驗通過後並刪除該token,並生成新的token返回
4、悲觀鎖和樂觀鎖:
悲觀鎖 : 更新數據時認爲此次操作會造成數據的缺失。
注意 : id字段必須時主鍵或者唯一索引,不然的話就鎖了整個表,導致效率降低,必須開啓事務,缺點容易造成死鎖,不建議使用
樂觀鎖 : 更新數據時認爲此次操作不會造成數據缺失,所以只是在更新數據那一刻鎖表,其他時間不鎖表,相對於悲觀鎖的效率更高。
實現方式 : 在數據庫的表中增加一個字段version(版本號)或者是其他的狀態位。在對錶進行操作時同時取出數據和標誌位version,當要修改數據表時,對version進行判斷是否與之前取出的一致,如果一致則修改,
如果不一致則不修改。同時version自增一存入數據庫。(注意 : 注意:樂觀鎖的更新操作,最好用主鍵或者唯一索引來更新,這樣是行鎖,否則更新時會鎖表)
5、分佈式鎖,加入系統部署在分佈式系統上,構建全局的唯一索引比較困難(唯一的字段無法沒法確定),這時候可以引入分佈式鎖,通過第三方的系統(redis或zookeeper),在業務系統插入數據或者更新數據,
獲取分佈式鎖,然後做操作,之後釋放鎖,這樣其實是把多線程併發的鎖的思路,引入多多個系統,
也就是分佈式系統中得解決思路要點:某個長流程處理過程要求不能併發執行,可以在流程執行之前根據某個標誌(用戶ID+後綴等)獲取分佈式鎖,其他流程執行時獲取鎖就會失敗,也就是同一時間該流程只能有一個能執行成功,
執行完成後,釋放分佈式鎖(分佈式鎖要第三方系統提供);
6、狀態機制,在設計單據相關的業務,或者是任務相關的業務,肯定會涉及到狀態機(狀態變更圖),就是業務單據上面有個狀態,狀態在不同的情況下會發生變更,一般情況下存在有限狀態機,
這時候,如果狀態機已經處於下一個狀態,這時候來了一個上一個狀態的變更,理論上是不能夠變更的,這樣的話,保證了有限狀態機的冪等。

總之冪等性,是最符合用戶使用的邏輯的,也是不會輕易出錯的,特別是在金融,銀行等涉及到交易支付的行業。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章