冪等性

目錄

1.轉賬提現

2.發貨系統


冪等性在我們的實際開發中是比較常見的,例如轉賬提現、訂單發貨系統等。今天,我們就分這兩種場景對冪等性進行討論:

1.轉賬提現

假如讓我們實現支付寶和銀行的轉賬提現需求,你會怎麼做呢?

首先我們看一下示意圖:

用戶登錄支付寶發起提現請求,支付寶調用銀行的出款接口,再將相關記錄落入數據庫。正常情況下,這個流程沒有問題,可是如果有一天銀行的出款接口超級慢,或者乾脆掛掉了,應該如何處理呢?我們如果直接提示,“出款失敗,請明天再來或者稍後再試”這樣的字樣顯示是非常不友好的,會帶來用戶的損失。正確的做法應該是?

  1. 假如是因爲接口超時導致無法出款的話,我們可以做一次接口重試。當然,銀行的接口必須滿足冪等性,防止重複提交導致重複扣款。此時的冪等性可以使用一個提交的版本號,銀行系統遇到和之前處理請求的版本號相同或者小的版本號,就不做處理。
  2. 銀行系統接口假如沒有實現冪等性呢?這在現實中是非常常見的,此時我們可以給用戶返回成功,保存用戶的請求,後面定時提交。

2.發貨系統

電商行業的發貨系統通常是這樣的,用戶提交訂單,訂單系統調用發貨接口開始發貨,並將相關記錄落庫。示意圖如下:

發貨系統提供的發貨接口爲:

  • 接口地址:http://127.0.0.1:9080/trans/sendOrder?order=1
  • 接口參數:order=1 訂單號爲1
  • 接口方法:對訂單1進行發貨

當系統頁面很卡頓的時候,用戶在頁面連續點擊了多次相同的請求,會出現什麼結果呢?如果不做冪等性處理,有可能多次調用發貨系統,導致一個訂單發貨多次,此時我們可以使用版本號的方式解決該問題。首先新建一張訂單表:

CREATE TABLE `order` (
  `orderid` VARCHAR(32) DEFAULT NULL,
  `ordertime` DATETIME DEFAULT NULL,
  `ordermoney` DECIMAL(20,0) DEFAULT NULL,
  `orderstatus` CHAR(1) DEFAULT NULL,
  `version` INT(11) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

利用數據庫的事務的原子性,當對該表有更新操作的時候,同時更新版本號。例如存在如下未發貨訂單記錄:

('1','2017-12-06 11:36:23','12','1',0)

1表示已經付款,2表示發貨中。當訂單執行發貨的時候執行如下SQL:

update order set orderstatus=2,version=version+1 where orderstatus = 1 and version = 0 

這樣通過引入版本號,就可以避免重複發貨的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章