動態

詳情 返回 返回

淺談冪等設計 | 京東雲技術團隊 - 動態 詳情

1 冪等性

一句話,冪等就是一個執行操作,無論執行多少次,產生的效果和返回的結果都是一樣的。

2 為什麼要實現冪等性?

如今隨着互聯網技術快速發展,業務越來越複雜,系統的高併發和關鍵數據的場景越來越多。

在分佈式系統中,機器宕機和消息丟失也是需要重點關注的問題,其中的一個典型就是冪等性問題。

想想看,一個對外暴露的接口會面領很多次請求,如果不能保證冪等性會帶來什麼樣的後果?

微信進行一次扣款操作,應該只扣用户一次錢,當遇到網絡故障或系統bug,如果沒有實現冪等性扣多了你會不會直接“C語言”投訴?

當然,有些接口是天然保證冪等性的,比如查詢操作、刪除操作。有些對數據的修改是一個常量,無其他操作,也是具有冪等性的。修改操作可能冪等可能不冪等。

SELECT col1 FROM tab1 WHERE col2 = 2UPDATE tab1 SET col1 = 1 WHERE col2 = 2UPDATE tab1 SET col1 = col1 + 1 WHERE col2 = 2

這三個sql只有第三個不是冪等的。

POST請求天生就不是一個冪等操作,每次調用都會在系統中產生新的資源,想要冪等就必須在業務中實現。

需要避免的是,冪等性和併發安全不是一回事。當同一筆訂單即使你不停的提交支付,如果扣了不止一次錢,就説明該操作不冪等。

而有多筆訂單同時進行支付,最後扣除的金額不是這麼多筆金額的總和,説明該操作有併發安全問題。這是兩個維度的問題,應該分開討論解決。

3 如何實現冪等性?

(1)數據庫防重

利用數據表唯一索引的特性,當併發時新增報錯時,再查詢一次,數據已經存在,就避免了髒數據的新增。但注意,不要將uuid作為索引字段,其大小和類型對於索引而言都會導致速度非常慢。

常見的場景,比如博客/微博系統點贊,一個用户對一個微博點贊,就把用户id與該博文id綁定,後續該用户再對該博文點贊就無法插入。再比如金融賬户,可以通過在賬户表中增加唯一索引來存儲用户id,即使重複操作一個用户也只能擁有一個賬户。

(2)token令牌機制

token機制是適用範圍最廣泛的一種冪等設計。雖然實現方式有很多種,但核心思想就是每次操作都生成一個唯一token憑證,服務器通過這個唯一憑證確保同樣的操作不會被執行多次。

具體可以分為兩個階段,獲取token和使用token。每次接口請求前先獲取一個token,然後在下次請求時在請求的header體中加上這個token,後端進行校驗,如果驗證通過則刪除token,下次請求再次判斷token。如果在redis緩存的幫助下,流程圖如下:

(3)分佈式鎖

數據庫防重表可以通過分佈式鎖代替,相比去重表,將放併發做到了緩存中,效率更高。侷限性都是同一時間只能完成一次請求。

比如某些業務處理流程很長,要求不能併發執行,可以在流程執行之前根據某個標誌(用户ID+後綴等)獲取分佈式鎖,其他流程執行時獲取鎖就會失敗,也就是同一時間該流程只能有一個能執行成功,執行完成後,釋放分佈式鎖。

4 冪等的優缺點

優點:

業務需要

缺點:

(1)客户端處理邏輯得以簡化,但服務端控制冪等邏輯變得更加複雜;

(2)把併發執行變成改為串行執行,降低了執行效率。

5 擴展

分佈式自增ID可以借鑑Snowflake算法,優點是高性能、低延遲、按時間有序;缺點是需要獨立的開發和部署。

其結構如下:

  • 最高位是符號位,始終為0,不可用。
  • 41位的時間序列,精確到毫秒級,41位的長度可以使用 (1L << 41) / (1000L 60 60 24 365) = 69年。時間位還有一個很重要的作用是可以根據時間進行排序。注意,41位時間截不是存儲當前時間的時間截,而是存儲時間截的差值(當前時間截 - 開始時間截) 後得到的值,這裏的的開始時間截,一般是我們的id生成器開始使用的時間,由我們程序來指定的。
  • 10位的機器標識,10位的長度最多支持部署1024個節點。
  • 12位的計數序列號,序列號即一系列的自增id,可以支持同一節點同一毫秒生成多個ID序號,12位的計數序列號支持每個節點每毫秒產生4096個ID序號。

加起來剛好64位,為一個Long型。這個算法很簡潔,但依舊是一個很好的ID生成策略。

參考文獻:

[1] 分佈式系統互斥性與冪等性問題的分析與解決

https://zhuanlan.zhihu.com/p/22820761

[2] 高併發下接口冪等性解決方案

https://blog.csdn.net/u011635492/article/details/81058153

[3] 冪等性問題和解決方法

https://blog.csdn.net/qq_32020035/article/details/105448889

[4] 雪花算法

https://www.cnblogs.com/grasp/p/12309726.html

[5] 聊聊開發中冪等問題

https://segmentfault.com/a/1190000018808510

作者:京東零售 李澤陽

來源:京東雲開發者社區 轉載請註明來源

user avatar lfree 頭像 yishenjiroudekaixinguo 頭像 wuliaodeqie 頭像 ethanprocess 頭像 gaoxingdeqincai 頭像 xiaoyanjingdepidan 頭像 huaihuaidedianti 頭像 nathannie 頭像 jixingsuiyuan 頭像 chen_6016206b422ca 頭像 htdaydayup_5da2d7a6d4888 頭像 tuzixiansen_63d4d65909d62 頭像
點贊 12 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.