溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解接口的冪等性的多重考慮

發(fā)布時間:2021-10-23 17:50:17 來源:億速云 閱讀:119 作者:iii 欄目:編程語言

本篇內(nèi)容主要講解“如何理解接口的冪等性的多重考慮”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何理解接口的冪等性的多重考慮”吧!

正文

1 接口冪等性

     就是說在多次相同的操作下保證最終的結(jié)果是一致的。

    其實這個概念還是比較簡單的,很容易理解,那我們思考一個問題,如果不保證接口冪等性會有什么問題?

1.1 案例

    我們簡單的舉個例子,現(xiàn)在有一個接口,提供了轉(zhuǎn)賬的功能,a要給b轉(zhuǎn)賬1000元,正常情況下我們接口一次性就調(diào)用成功了,但是卻因為網(wǎng)絡抖動等其它原因沒有成功,于是就開始不停的重試,突然網(wǎng)絡好了,但是這時卻連續(xù)發(fā)出去了三個請求,但是這個接口沒有保證冪等性,于是從結(jié)果上來看就是a給b轉(zhuǎn)了3000元,這顯然是程序業(yè)務邏輯上不能接受的(其實moon可以當b的)。

2 解決方案

2.1 token機制

    token機制其實是比較簡單的,我們先來簡單的說一下流程。</br>

  • 首先客戶端先請求服務端,服務端生成token,每次請求生成的都是一個新的token(這個token一定要設(shè)置超時時間),將token存入redis當中,然后將token返回給客戶端。

  • 客戶端攜帶剛剛返回的token請求服務端做業(yè)務請求

  • 服務端收到請求,做判斷。

    • 如果token在redis中,則直接刪除該token,然后繼續(xù)做業(yè)務請求。

    • 如果token不在redis中,代表已經(jīng)執(zhí)行過當前業(yè)務了,則不執(zhí)行業(yè)務。

    圖示如下:

如何理解接口的冪等性的多重考慮

    token機制實現(xiàn)方式還是比較簡單的,但是其實對于我們某些響應速度要求很高的業(yè)務不太友好,缺點就是需要多一次請求獲取token的過程。

    正常來說是每次請都會生成一個新的token,如果有極限情況下,有兩個請求都帶著相同的token進來,會存在都走入判斷是否存在的過程,可能都會同時查到存在,這樣也會有問題,針對這種情況,我們可以在刪除前判斷下是否存在,存在就刪除,為了保證原子性,這部分邏輯建議使用lua腳本完成。

2.2 去重表

    去重表的機制是根據(jù)mysql唯一索引的特性來的,我們先來說下它的流程:

  • 首先客戶端先請求服務端,服務端先將這次的請求信息存入一張mysql的去重表中,這張表要根據(jù)這次請求的其中某個特殊字段建立唯一索引,或者主鍵索引

  • 判斷是否插入成功

    • 如果插入成功,則繼續(xù)做后續(xù)業(yè)務請求。

    • 如果插入失敗,則代表已經(jīng)執(zhí)行過當前請求。

    圖示如下:

如何理解接口的冪等性的多重考慮

    去重表機制的問題有兩點:

  • 1.mysql容錯性,也就是mysql本身如果不是高可用的那么業(yè)務可能會受到影響:

  • 2.既然是唯一索引,自然在寫表的時候就沒有辦法用到changbuffer,每次都要從磁盤查出來判斷再寫入,對于一個高并發(fā)的接口來說,這些都是需要考慮的因素。

2.3 redis 的 SETNX鍵值

    過程如下:

  • 首先客戶端先請求服務端,服務端將能代表這次請求業(yè)務的唯一字段以 SETNX 的方式存入redis,并設(shè)置超時時間,超時時間可以根據(jù)業(yè)務權(quán)衡。

  • 判斷是否插入成功

    • 如果插入成功,則繼續(xù)做后續(xù)業(yè)務請求。

    • 如果插入失敗,則代表已經(jīng)執(zhí)行過當前請求。

    這里我們是利用了redis setnx 的特性來完成的。</br>

    setnx:只在鍵key不存在的情況下,將鍵key的值設(shè)置為value。若鍵key已經(jīng)存在,則SETNX命令不做任何動作。命令在設(shè)置成功時返回1,設(shè)置失敗時返回0。

    圖示如下:

如何理解接口的冪等性的多重考慮

    這種方案可以說是針對上一個方案改進的,效率也會提高很多。

2.4 狀態(tài)機冪

    這種機制適用于有不同狀態(tài)的業(yè)務,moon的上一家公司就是這樣做的。

    我們的訂單系統(tǒng),一條訂單會有多個狀態(tài),如:待付款,鎖定,已付款等狀態(tài),而這些狀態(tài)都是有流程和邏輯的,我們可以根據(jù)這個狀態(tài)判斷是否執(zhí)行后續(xù)業(yè)務操作。

2.5 樂觀鎖(更新操作)

    就是數(shù)據(jù)庫中增加版本號字段,每次更新根據(jù)版本號來判斷

    過程如下:

  • 首先客戶端先請求服務端,先查詢出當前的version版本。

    • select version from .. where ..

  • 根據(jù)version版本來做sql操作

    • UPDATE .. SET ... version=(version+1) WHERE .. AND version=version;

    這個圖示我就不再畫了,還是比較簡單的

2.6 悲觀鎖(更新操作)

    假設(shè)每一次拿數(shù)據(jù),都有認為會被修改,所以給數(shù)據(jù)庫的行上鎖,也是基于數(shù)據(jù)庫特性來完成。

     當數(shù)據(jù)庫執(zhí)行select for update時會獲取被select中的數(shù)據(jù)行的行鎖,因此其他并發(fā)執(zhí)行的select for update如果試圖選中同一行則會發(fā)生排斥(需要等待行鎖被釋放),因此達到鎖的效果。

START TRANSACTION; # 開啟事務
SELETE * FROM TABLE WHERE .. FOR UPDATE;
UPDATE TABLE SET ... WHERE ..;
COMMIT; # 提交事務

到此,相信大家對“如何理解接口的冪等性的多重考慮”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI