業(yè)務(wù)場(chǎng)景
一般的商城業(yè)務(wù)中,我們經(jīng)常會(huì)遇到一種場(chǎng)景,某商品庫(kù)存只剩最后一件,但此時(shí)有多個(gè)用戶(hù)同時(shí)下單,如果沒(méi)有做任何的處理,多個(gè)用戶(hù)下單時(shí)進(jìn)程讀取到的庫(kù)存為1,程序判斷符合扣庫(kù)存條件,下單成功,就會(huì)造成庫(kù)存變成負(fù)數(shù)的情況
解決方案
思路
樂(lè)觀鎖通過(guò)增加一個(gè)每次更新庫(kù)存都會(huì)自增的version字段來(lái)解決這個(gè)問(wèn)題,每個(gè)進(jìn)程讀取庫(kù)存字段的同時(shí),也會(huì)讀取version的值,在更新庫(kù)存同時(shí)更新version,并增加對(duì)version字段值的判斷
代碼實(shí)現(xiàn)
<!-- 樂(lè)觀鎖更新庫(kù)存 -->
<update id="newMinStock" parameterType="java.util.Map">
update goods
set stock= stock - 1,version = #{version} + 1
where id = #{id} and version = #{version}
</update>
假設(shè)有兩個(gè)進(jìn)程都讀取到了stock的值為1,version默認(rèn)值為0,則這兩個(gè)進(jìn)程執(zhí)行的更新語(yǔ)句都是update goods set stock=stock-1,version=version+1 where id=1 and version=0,當(dāng)其中一個(gè)進(jìn)程執(zhí)行成功之后,數(shù)據(jù)庫(kù)中version的值就會(huì)變?yōu)?,剩下的進(jìn)程不會(huì)執(zhí)行成功,這樣保證了stock的值不會(huì)小于0
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("version", version);
int result = goodsMapper.newMinStock(map);
if (result != 1) {
throw new RuntimeException("更新商品庫(kù)存失敗");
}
在業(yè)務(wù)層判斷更新庫(kù)存是否成功,進(jìn)行相應(yīng)的業(yè)務(wù)處理