為了解決併發下的商戶限額問題,由於服務是分布式的方式部署在多台伺服器上的,故選擇樂觀鎖為解決方案。
即使用資料版本(version)記錄機制實現,這是樂觀鎖最常用的一種實現方式。何謂資料版本?即為資料增加乙個版本標識,一般是通過為
資料庫表增加乙個數字型別的 「version」 欄位來實現。當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加一。當我們提交更新的時候,判斷
資料庫表對應記錄的當前版本資訊與第一次取出來的version值進行比對,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期資料。
在這裡是直接進行限額更新然後進行邏輯操作,也就是在限額累加之後實際上並沒有實際扣款,所以如果之後的交易扣款失敗,要回滾限額。
merchant merchant = order.getmerchant();
map paramap = new hashmap();
int updatesecflag = 0;//更新限額成功標誌
int i =0;//計數器
paramap.put(dict.merchantid, merchant.getid());
doif (!constants.mertransctrl_ok.equals(mtc.getstatus()))
// 訂單金額大於商戶單筆金額
if (order.getamount().compareto(mtc.getpertranslimit()) > 0)
date today = (date) ctx.getdata(dict.pptransdate);
dateformat df = miscutil.getdateformat("yyyymmdd");
string todaystr = df.format(today);
if (mtc.getdayamtdate() != null && todaystr.equals(df.format(mtc.getdayamtdate())))
//更新當日限額
mtc.setdayamt(mtc.getdayamt().add(order.getamount()));
updatesecflag = this.getsqlmap().update("pp.core.updatemertransctrl", mtc);
} else
//更新當日限額和交易日期
mtc.setdayamt(order.getamount());
mtc.setdayamtdate(today);
mtc.setversion(1);
updatesecflag = this.getsqlmap().update("pp.core.updatemertransctrlforonece", mtc);
}i++;
}while(updatesecflag != 1 && i<100);
如果是當日的第一筆交易,更新累計金額為當筆實際支付金額並將version設定為「1」。
日間情況查表sql
update
ft_mer_transctrl
setmertc_pertranslimit=#pertranslimit#
mertc_perdaylimit=#perdaylimit#
mertc_dayamt=#dayamt#
mertc_dayamtdate=#dayamtdate#
mertc_status=#status#
mertc_closedate=#closedate#
channel_modifydate=#modifydate#
mertc_openuser=#openuser#
channel_closeuser=#closeuser#
version=#version#+1
where
mer_id = #merchantid#
andversion = #version#
如果是過期資料查表失敗則拿到當前版本重新操作。認為100次應該是足夠滿足我們的業務要求的,故在此設定了乙個迴圈限制。
如果後續轉賬交易失敗,要回滾已累加的限額。過程和之前類似。
Redis 樂觀鎖控制事務
redis對事務的支援比較簡單。redis只能保證乙個客戶端發起的事務命令可以執行,中間不會插入其他事務。因為redis是單執行緒的,所以做到上面這點很容易。一般redis接受到客戶端的命令後會立即執行,但是如果客戶端發起multi命令,redis不會立即執行,而是讓當前連線進入事務上下文,把命令放...
Redis樂觀鎖控制事務
redis對事務的支援比較簡單。redis只能保證乙個客戶端發起的事務命令可以執行,中間不會插入其他事務。但 redis集群不支援事務。因為redis是單執行緒的,所以做到上面這點很容易。一般redis接受到客戶端的命令後會立即執行,但是如果客戶端發起multi命令,redis不會立即執行,而是讓當...
併發控制 悲觀鎖和樂觀鎖詳解
考慮下面兩個併發帶來的問題 1 丟失更新 乙個事務的更新結果覆蓋了其它事務的更新結果,即所謂的更新丟失。2 髒讀 當乙個事務讀取其它完成一半事務的記錄時,就會發生髒讀取。例如 兩個使用者同時修改商品庫存表,a b同時進入,看到的庫存都是100,a購買一件把庫存修改為99 100 1 此時b購買兩件把...