日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redisson分布式锁实战(适用于Redis高并发场景)

發布時間:2025/1/21 数据库 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redisson分布式锁实战(适用于Redis高并发场景) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實現方式一:存在拋異常后lock值無法歸0的問題

@Autowired private StringRedisTemplate stringRedisTemplate;@RequestMapping("deduct_stock")public void deductStock(){Long num = stringRedisTemplate.opsForValue().increment("lock", 1);//多個線程過來 只有一個線程會將num值設置為1 其余的線程都不可能為1if (num==1){int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock>0){stringRedisTemplate.opsForValue().set("stock",(stock-1)+"");System.out.println("扣減成功,庫存stock:"+(stock-1)+"");}else{System.out.println("扣減失敗,庫存不足");}}//還原stringRedisTemplate.opsForValue().increment("lock",-1);}

實現方式二:加try…finally。無論程序是否拋出異常,最終都會還原。但是在還原為0的時候有可能redis掛了,或者是程序還沒執行完try代碼塊中的內容,整個web應用掛掉了,finally塊中的內容也無法執行。即使程序重啟,后面的線程也始終無法滿足num==1的條件。

@Autowired private StringRedisTemplate stringRedisTemplate;@RequestMapping("deduct_stock") public void deductStock(){try{Long num = stringRedisTemplate.opsForValue().increment("lock", 1);//多個線程過來 只有一個線程會將num值設置為1 其余的線程都不可能為1if (num==1){int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock>0){stringRedisTemplate.opsForValue().set("stock",(stock-1)+"");System.out.println("扣減成功,庫存stock:"+(stock-1)+"");}else{System.out.println("扣減失敗,庫存不足");}}}finally {//還原stringRedisTemplate.opsForValue().increment("lock",-1);} }

實現方式三:設置lock的超時時間。存在這么一個場景,由于某一段時間內,網絡環境差,導致本應10秒內就執行完的程序執行了15秒才完成,而鎖已經過期了,也就意味著后面的線程能拿到鎖,導致鎖形同虛設。
還存在這么一個情況:第一個線程執行時長15秒,假設第二個線程執行時長8秒,由于鎖已失效,第二個線程是能重新拿到新鎖的,結果第一個線程在執行歸0操作釋放鎖時,它自己的鎖已失效,導致釋放的并不是自己的鎖,而是第二個線程的鎖。總之,存在一系列場景導致鎖失效。

@Autowired private StringRedisTemplate stringRedisTemplate;@RequestMapping("deduct_stock") public void deductStock(){try{String lockkey = "lock";Long num = stringRedisTemplate.opsForValue().increment(lockkey, 1);//給key設置超時時間 到期自動清理stringRedisTemplate.expire(lockkey,10, TimeUnit.SECONDS);//多個線程過來 只有一個線程會將num值設置為1 其余的線程都不可能為1if (num==1){int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock>0){stringRedisTemplate.opsForValue().set("stock",(stock-1)+"");System.out.println("扣減成功,庫存stock:"+(stock-1)+"");}else{System.out.println("扣減失敗,庫存不足");}}}finally {//還原stringRedisTemplate.opsForValue().increment("lock",-1);} }

這種場景下,可以開啟一個分線程,與當前線程綁定,如果鎖的失效時間是10秒,那么就每隔5秒去掃描一下這把鎖,看看鎖是否還在,如果還在就再次將失效時間重置為10秒,不斷延時,也就相當于讓這把鎖具備了自動延時的功能,直到當前線程親自將這把鎖釋放,否則一致延時下去。

Redisson框架實現分布式鎖

上述分析也就是Redisson的實現原理,只不過會增加一個線程,讓等待的線程不斷地嘗試加鎖,通過while循環來實現的,俗稱就是自旋加鎖。

配置單機Redis

/*** @ProjectName springbootdemo_src* @ClassName RedissionConfig* @Desicription TODO* @Author Zhang Xueliang* @Date 2019/7/27 17:34* @Version 1.0**/ @Configuration public class RedissonConfig {@Bean("redisson")//如果不寫value 默認就會以方法名作為bean的名稱進行注入public Redisson getRedisson(){Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(0);return (Redisson) Redisson.create(config);} }

加鎖代碼:很簡單,就三行代碼。重要的是理解運行原理。

/*** @ProjectName springbootdemo_src* @ClassName RedissionController* @Desicription TODO* @Author Zhang Xueliang* @Date 2019/7/27 15:55* @Version 1.0**/@SuppressWarnings("all") @RestController public class RedissionController {@Autowiredprivate Redisson redisson;@RequestMapping("redisson_lock")public void redissonDeductStock() {String lockkey = "lock";RLock lock = redisson.getLock(lockkey);try {lock.lock();//如果使用默認的午餐lock方法 默認超時時間設置的是30秒 可以傳入自定義的超時時間int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock > 0) {stringRedisTemplate.opsForValue().set("stock", (stock - 1) + "");System.out.println("扣減成功,庫存stock:" + (stock - 1) + "");} else {System.out.println("扣減失敗,庫存不足");}} finally {lock.unlock();}}}

Redisson實質上就是給代碼加上了一把悲觀鎖,而悲觀鎖是比較影響性能的。increment自增加1的方式實質是樂觀鎖。
Redis天生就是單線程的,在高并發環境主從集群還是會存在一定問題。

總結

以上是生活随笔為你收集整理的Redisson分布式锁实战(适用于Redis高并发场景)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。