日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

幂等性问题和解决方法

發(fā)布時間:2023/12/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 幂等性问题和解决方法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在實際的開發(fā)項目中,一個對外暴露的接口往往會面臨很多次請求。這就需要考慮到一個冪等性問題。

冪等性

冪等性的概念是:任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同,即無論你請求了多少次,對數(shù)據(jù)庫的影響都只能有一次,不能重復(fù)處理。

所以,按照上面的理解,每次執(zhí)行的結(jié)果都會發(fā)生變化,就是非冪等的。如下面三條sql,只有第三條是非冪等的。

SELECT col1 FROM tab1 WHER col2=2,無論執(zhí)行多少次都不會改變狀態(tài),是天然的冪等。UPDATE tab1 SET col1=1 WHERE col2=2,無論執(zhí)行成功多少次狀態(tài)都是一致的,因此也是冪等操作。UPDATE tab1 SET col1=col1+1 WHERE col2=2,每次執(zhí)行的結(jié)果都會發(fā)生變化,這種不是冪等的。

http和冪等性

這里就可以牽扯到http請求了。http請求的get方法是冪等性的,因為不會對數(shù)據(jù)庫造成更改影響,每次返回的數(shù)據(jù)都一致。而post請求是非冪等的,因為每請求一次都會添加一條數(shù)據(jù)

(按restful規(guī)范,post常規(guī)是添加數(shù)據(jù)時使用。當(dāng)然,也有例外,我們有的時候可能需要把查詢方法改造成 POST 方法。比如,超長(1k)的 GET URL 使用 POST 方法來替代,因為 GET 受到 URL 長度的限制。雖然,它不符合冪等性,但是它是一種折中的方案。)

因此 根據(jù)restful的規(guī)范,http的請求會有以下是否冪等性的判斷。

Http method操作是否冪等
get獲取數(shù)據(jù)
post新建數(shù)據(jù)×
put更新所有數(shù)據(jù)
patch更新部分?jǐn)?shù)據(jù)×
delete刪除資源

為什么要設(shè)計冪等性的服務(wù)

冪等可以使得客戶端邏輯處理變得簡單,但是卻以服務(wù)邏輯變得復(fù)雜為代價。滿足冪等服務(wù)的需要在邏輯中至少包含兩點:

  • 首先去查詢上一次的執(zhí)行狀態(tài),如果沒有則認(rèn)為是第一次請求
  • 在服務(wù)改變狀態(tài)的業(yè)務(wù)邏輯前,保證防重復(fù)提交的邏輯
  • 冪等的不足

    冪等是為了簡化客戶端邏輯處理,卻增加了服務(wù)提供者的邏輯和成本,是否有必要,需要根據(jù)具體場景具體分析,因此除了業(yè)務(wù)上的特殊要求外,盡量不提供冪等的接口。

  • 增加了額外控制冪等的業(yè)務(wù)邏輯,復(fù)雜化了業(yè)務(wù)功能;
  • 把并行執(zhí)行的功能改為串行執(zhí)行,降低了執(zhí)行效率。
  • 冪等性解決方案

  • 防重表
    數(shù)據(jù)庫建立唯一性索引,可以保證最終插入數(shù)據(jù)庫的只有一條數(shù)據(jù)(比如訂單表對訂單號進(jìn)行唯一索引,所有重復(fù)提交可能產(chǎn)生同一個訂單號的都會被拆除。當(dāng)然,訂單號要按你自己的設(shè)定走,一般訂單號設(shè)計會是時間戳加迭代。那么如果是這樣,創(chuàng)建仍然不能保證冪等,具體根據(jù)業(yè)務(wù)需求來判定建立的唯一索引位置)
  • token令牌機(jī)制,
    分為兩個階段,獲取token和使用token。每次接口請求前先獲取一個token,然后再下次請求的時候在請求的header體中加上這個token,后臺進(jìn)行驗證,如果驗證通過刪除token,下次請求再次判斷token。如果使用上redis緩存,流程圖會是這樣。
  • 先查詢后判斷,
    首先通過查詢數(shù)據(jù)庫是否存在數(shù)據(jù),如果存在證明已經(jīng)請求過了,直接拒絕該請求,如果沒有存在,就證明是第一次進(jìn)來,直接放行。
  • 支付緩沖區(qū)
    把訂單的支付請求都快速地接下來,一個快速接單的緩沖管道。后續(xù)使用異步任務(wù)處理管道中的數(shù)據(jù),過濾掉重復(fù)的待支付訂單。優(yōu)點是同步轉(zhuǎn)異步,高吞吐。不足是不能及時地返回支付結(jié)果,需要后續(xù)監(jiān)聽支付結(jié)果的異步返回。(一般支付都是采用這種方式)
  • 悲觀鎖或者樂觀鎖。
    悲觀鎖可以保證每次for update的時候其他sql無法update數(shù)據(jù)(在數(shù)據(jù)庫引擎是innodb的時候,select的條件必須是唯一索引,防止鎖全表)
    樂觀鎖,一般通過version來做樂觀鎖,這樣既能保證執(zhí)行效率,又能保證冪等。例如: UPDATE tab1 SET col1=1,version=version+1 WHERE version=#version# 不過,樂觀鎖存在失效的情況,就是常說的ABA問題,不過如果version版本一直是自增的就不會出現(xiàn)ABA的情況。(ABA可以查看這篇文章鏈接,關(guān)于CAS機(jī)制可以看這篇鏈接)
  • 分布式鎖
    防重表可以使用分布式鎖代替,比如Redis。訂單發(fā)起支付請求,支付系統(tǒng)會去Redis緩存中查詢是否存在該訂單號的Key,如果不存在,則向Redis增加Key為訂單號。查詢訂單支付已經(jīng)支付,如果沒有則進(jìn)行支付,支付完成后刪除該訂單號的Key。通過Redis做到了分布式鎖,只有這次訂單訂單支付請求完成,下次請求才能進(jìn)來。相比去重表,將放并發(fā)做到了緩存中,較為高效。思路相同,同一時間只能完成一次支付請求。
  • 總結(jié)

    以上是生活随笔為你收集整理的幂等性问题和解决方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。