高並發下樂觀鎖實現


目前有業務並發更新某業務表,比如用戶賬戶表,可考慮利用數據庫樂觀鎖的辦法解決。

1、表設計

     需要在表中新增version字段,可定義為bigint類型,初始值可設置為0

2、更新語句mybatis的實現

<update id="updateConsumeStarWithLook">
        update sys_user_consume_star 
            set current_consume_star_amount = #{currentConsumeStarAmount},
                update_time = #{updateTime, jdbcType=TIMESTAMP},
                version = version + 1
            where id = #{id} and version = #{version}
    </update>

3、業務邏輯層,實現思路:可定義一個更新方法,先查詢出當前記錄,根據業務進行調用樂觀鎖實現的updateConsumeStarWithLook,如果更新成功,即該返回值為1時,表示更新成功,當返回值為0時,表示未成功更新,可再次遞歸調用該更新方法。

private void updateUserConsumeStarWithLook(String userId,Long starAmount) { Wrapper<SysUserConsumeStar> wrapper = new QueryWrapper<SysUserConsumeStar>() .eq("user_id", userId); SysUserConsumeStar sysUserConsumeStar = sysUserConsumeStarService.getOne(wrapper); Long oldStartAmount = sysUserConsumeStar.getCurrentConsumeStarAmount(); Long newStartAmount = oldStartAmount + starAmount; sysUserConsumeStar.setCurrentConsumeStarAmount(newStartAmount).setUpdateTime(LocalDateTime.now()); Integer result = sysUserConsumeStarService.updateConsumeStarWithLook(sysUserConsumeStar); //如果更新失敗則繼續嘗試直到成功為止
        if(result == 0) { updateUserConsumeStarWithLook(userId,flowType,starAmount); } }

4、在具體調用上述方法的方法上如果需要加上事務,則需要將事務的隔離級別定義為讀已提交,不然在查詢的時候會出現臟讀,更新無法成功,導致死循環

@Transactional(rollbackFor = Exception.class,isolation=Isolation.READ_COMMITTED,propagation=Propagation.REQUIRED)

 5、測試,可使用JMater,相關教程可參考:https://blog.csdn.net/u010481688/article/details/81032259


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM