冪等講的是一個操作無論是我們執(zhí)行一次還是無數(shù)次,所產(chǎn)生的影響是一樣的恤浪。
在我們應(yīng)用系統(tǒng)中畅哑,有時因為系統(tǒng)超時等原因,需要調(diào)用方重試水由,如果這個時候沒有設(shè)計好一個冪等方案荠呐,則會對系統(tǒng)帶來副作用,比如多創(chuàng)建一比訂單砂客。
要做到冪等性的交易接口泥张,首先需要一個唯一的標(biāo)識,來標(biāo)志交易是同一筆交易鞠值,而這個交易ID由誰來分配也是一件頭疼的事媚创,這個標(biāo)識需要做到全局唯一。
如果由一個中心系統(tǒng)來分配彤恶,那么每一次交易都需要找那個中心系統(tǒng)钞钙,這樣增加了程序的性能開銷,如果由上游系統(tǒng)來生成声离,則可能導(dǎo)致ID重復(fù)的問題芒炼,因為上游系統(tǒng)可能會是一個集群,它們同時承擔(dān)相同的工作术徊。
另外全局ID生成本刽,我們需要使用一個不會沖突的算法,比如使用UUID這樣沖突非常小的算法赠涮,但是它的字符串占用空間比較大子寓,索引效率很低,ID值不具備可讀性笋除,且沒有遞增斜友,無法實現(xiàn)排序。
目前比較好的方案是使用Twitter的雪花算法垃它。另外其他的像Redis,Zookeeper,MongoDB的ID的生成算法也是比較好的選擇鲜屏。
實現(xiàn)冪等設(shè)計的核心處理流程
對于冪等性的處理流程來說,就是要過濾一下已經(jīng)收到的交易嗤瞎,要做到這個事墙歪,那我們先需要一個存儲來記錄收到的交易。因為我們的冪等服務(wù)是分布式的贝奇,所以需要這個存儲也是共享的虹菲,通常可以使用關(guān)系型數(shù)據(jù)庫掉瞳,也可以使用key-value的NoSQL(如Redis)來構(gòu)建這個存儲毕源。
上述流程節(jié)本實現(xiàn)了冪等浪漠,但是有個問題,因為絕大多數(shù)請求應(yīng)該不是重發(fā)過來的霎褐,所以讓所有的請求都到存儲里查詢交易址愿,這會導(dǎo)致處理流程變慢。
所以冻璃,我們可以通過思考在sql中做優(yōu)化响谓,使其能實現(xiàn)冪等。比如是插入操作省艳,則使用 insert into ... values .. on duplicate key update . 如果是更新操作娘纷,則使用 update tabel set money = money + 10 where id = xxx and version = v1.