搜尋

首頁  >  問答  >  主體

java - 怎么理解在生成订单的时候幂等性的控制

经常听人说在交易系统中,生成订单的时候要控制好两个:一个是幂等性的控制,一个是并发性的控制。
我的理解是这样的,并发性的控制,可以从数据库层面上,利用锁表中行的操作,分布式锁的方式来实现并发性,那么幂等性呢?查了一些资料对于幂等性这个概念的理解,还是越看越模糊,有没有什么通俗的对于幂等性的解释呢?此外怎么在生成订单的系统中做好幂等性的控制呢?
所以我的问题是:
1、怎么通俗的理解幂等性 ?
2、如何在项目中做到幂等性的控制,防止订单碎片的产生??

谢谢~~

天蓬老师天蓬老师2767 天前1128

全部回覆(8)我來回復

  • ringa_lee

    ringa_lee2017-04-18 09:27:43

    謝邀~其實你的理解的有錯的~不知道你這些資料是在哪裡看到的…
    實際上…解決並發問題…不單單是簡單的資料庫鎖能解決的…是需要透過一系列緩存、分流、過濾等共同實現的~
    而等冪性只是一個約定~約定用戶在同一操作中~生效的只有一個~例如用戶狂點下單~實際中生效的只有一個…解決方法很簡單~分2層…前端控制點一次就不能再點…後端做請求唯一標識~然後在快取中保存~之後真正生效的只有一個~

    感覺你這幾次問的問題更像是教科書中講的東西~實際應用中遠遠不是那樣的~建議可以關注下科技累的一些文章~例如淘寶寫的秒殺原理~阿里雲最近發表的高並發下紅包系統的架構等實際生產中總結的乾貨~

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-18 09:27:43

    冪等性是系統的介面對外一種承諾(而不是實現), 承諾只要呼叫介面成功, 外部多次呼叫對系統的影響是一致的. 聲明為冪等的介面會認為外部呼叫失敗是常態,且失敗之後必然會有重試.

    至於你說的防止訂單碎片,我所知道的就是依靠事務了,像支付寶那種高並發環境我也不清楚他們是用的什麼。

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-18 09:27:43

    用token啊,不只是能防止csrf,也能防UI層面的重播。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-18 09:27:43

    一個簡單的例子對冪等性的理解

    public class Main {
        private int i = 0;
        
        //这个方法不具有幂等性,每调用一次,它就会改变Main的状态(即改变了i)
        public void idempotent() {
            i++;
        }
        
        //幂等性,无论这个方法调用多少次,它都不会改变Main类的状态。
        public void simple() {
            System.out.println(i);
        }
    }

    我理解的打印訂單需要冪等性,是打印訂單時不能數據的狀態,同一個訂單無論打印多少次,不會影響到其它訂單的打印。這個很好控制啊,列印訂單的時候別修改資料庫的數據,把資料取到應用端再做處理,就不會對資料庫端造成碎片。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-18 09:27:43

    冥等性指的是對業務系統的調用,如果發生多次調用,對業務系統不會造成影響。
    這個需求是在做分散式系統中很重要,因為分散式系統中,靠資料庫本身已經無法完成事務的控制,會採用一些訊息佇列、非同步呼叫的方式,在碰到一些異常情況遠端呼叫狀態不明確的時候,會嘗試重新做一次遠端服務的調用,如果服務沒有冥等性保證的話,就不能用重試的機制了。

    對於創建訂單的場景,本身不是冥等性的,如果調用多次就會出現多張訂單。通常的處理辦法是在創建訂單前,根據傳遞過來的信息做查詢,如果已經執行過,就直接返回調用成功的信息,防止出現重複訂單。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-18 09:27:43

    冪等性你可以理解為HTTP裡面的GET請求(不要說你訪問同一網址有時候內容不一樣哈),POST請求就是非冪等性的。所以呢大多數時候,使用GET還是不錯的!也千萬不要覺得POST好像把body資料隱藏了就安全哈。

    回覆
    0
  • 迷茫

    迷茫2017-04-18 09:27:43

    冪等解決的是在分散式系統中如果出現了超時等網路原因,導致client不知道server到底是執行成功了還是失敗了。這時候需要client重試。如果介面不是冪等。會造成預期不同的結果。

    簡單的說一個介面如果是冪等的,你呼叫一次和多次效果都是一樣的。如

    UPDATE table SET NAME="LILEI" WHERE UID='1'

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-18 09:27:43

    雷雷

    回覆
    0
  • 取消回覆