1. 程式人生 > >高併發搶紅包案列以及使用鎖,版本號,redis快取解決,專案可執行,詳細註釋(二)

高併發搶紅包案列以及使用鎖,版本號,redis快取解決,專案可執行,詳細註釋(二)

1 悲觀鎖

<!-- 查詢紅包具體資訊 -->
<select id="getRedPacketForUpdate" parameterType="int"
    resultType="test814RedPacket.pojo.RedPacket">
    select id,user_id as userId,amount,send_date as sendDate,total,unit_amount as
    unitAmount,stock,version,note
    from T_RED_PACKET where id=#{id}  for update
</select>

  for update

在sql後面加 for update ,

注意,在 SQL 中加入的 for update 語句,意味著將持有對資料庫記錄的行更新鎖(因 為這裡使用主鍵查詢,所以只會對行加鎖。如果使用的是非主鍵查詢,要考慮是否對全表 加鎖的問題,加鎖後可能引發其他查詢的阻塞〉,那就意味著在高併發的場景下 條事 務持有了這個更新鎖才能往下操作,其他的執行緒如果要更新這條記錄,都需要等待,這樣 就不會出現超發現象引發的資料一致

發現一個好玩的問題:

在UserRedPacketServiceimpl 中,如果你註釋掉

 就是不要事務,還是會超發

 加上之後才不會。有趣

2樂觀鎖

說吧了就是判斷下之前的stock值有沒變化,有變化則說明資料改變,不操作。但是可能存在bab問題,所以加個版本,每次資料改變,版本+1,在對資料修改之前,判斷版本,沒有變化才操作資料。

<!-- 通過版本號扣減搶紅包 ,每更新一次,版本加1,其次增加對版本的判斷  注意 的代 減紅包的時 增加了對版本號的判斷,其次每次扣減都會對
版本號 ,這樣保證每次更新在版本號上有記錄 從而避免 ABA 問題。對於查詢也不使
for update 語旬 避免鎖 發生 這樣就沒有執行緒阻塞的 題了-->

<update id="decreaseRedPacketForVersion" >
 update T_RED_PACKET set stock = stock -1,version=version+1 where id =#{id} and version = #{version}
</update>

 這裡是主要改動,其餘都是改動呼叫,看下結果:

我設定了2500左右的人搶2000個紅包,看到沒,剩下不少.....

所以再優化,重入機制

也就是 旦因為版本原因 沒有搶到紅包,則重新嘗試搶紅包,但是過多的重入會造成大量的 SQL 執行,所以目前流 行的重入會加入兩種限制, 1種是按時間戳的重入,也就是在 定時間戳內不成功的會迴圈到成功為止,直至超過時間戳,不成功才會退出,返回失敗。另外 1種是按次數,比如限定 3次,程式嘗試超過3 次搶紅包後,就判定請求失效,這樣有助 於提高使用者搶紅包的成功率,下面討論如何重入。

加個時間而已,你也可以把時間換成次數

    for (int i = 0; i < 3; i++) {
            //獲取紅包資訊,
            RedPacket redPacket = redPacketMapper.getRedPacket(redPacketId);        
            //當前紅包數大於0
            if(redPacket.getStock()>0){
                //再次傳入執行緒儲存的 version 舊值給 SQL 判斷,是否有其他執行緒修改過資料            
                int  update = redPacketMapper.decreaseRedPacketForVersion(redPacketId,redPacket.getVersion());
                //如果沒有資料更新,說明其他執行緒已經更新過資料,本次搶紅包失敗
                if(update==0){
                    return FAILED;
                }

 

3 redis

對於使用 redis 實現搶紅包 首先需要知道的是redis的功能不如資料庫強大,事務也 不完整,因此要保證資料的正確性,資料的正確性可以通過嚴格的驗證得以保證。而  Lua 語言是原子性的,且功能更為強大 所以優先選擇使用 Lua 語言來實現搶紅包

 

下一篇文章介紹