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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redis分布式锁java代码_基于redis实现分布式锁

發布時間:2023/12/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis分布式锁java代码_基于redis实现分布式锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?在上一篇文章中介紹了動態配置定時任務,其中的原理跟spring 定時任務注解@Scheduled一樣的,都是通過線程池和定義執行時間來控制。來思考一個問題,如果我們的定時任務在分布式微服務里面呢?在分布式微服務里面一個微服務肯定可以有多個實例的,在上一篇文章當中配置的定時任務就會有可能存在多個,顯然定時任務被多次執行并不是我們想要的結果,這個時候我們的分布式鎖機制就出現了!

(分布式鎖有很多實現方式,以前我們都是使用synchronized來處理并發請求,雖然也支持分布式,但是總有一些業務不適合,比如秒殺系統的多個商品同時開啟秒殺,同一時刻只能完成一件商品的減庫存操作,這樣就造成了系統的性能瓶頸,也不符合秒殺系統的設計思想。由于 synchronized 無法做到細粒度的控制,從而引進了分布式鎖,分布式鎖能夠完成 synchronized 無法做到的點。下面我們要介紹的是基于redis的實現方式)。

01

引入redis依賴

引入springboot官方的redis依賴。

引入一個hutool工具包的依賴,功能很全的一個java工具包,強烈推薦使用。

<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-data-redisartifactId>dependency><dependency> <groupId>cn.hutoolgroupId> <artifactId>hutool-allartifactId> <version>5.3.2version>dependency>

02

基于redis實現

怎么使用redis實現呢,先來看下redis的兩個命令。

setnx:如果key不存在就跟set一樣的作用,如果key存在則什么都不做

getandset:返回上一次的value,并設置新的value

import cn.hutool.core.util.StrUtil;import cn.hutool.log.StaticLog;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Component;/** * redis分布式鎖 * * @author zhongxiaojian * @date 2020/4/17 **/@Componentpublic class LockUtil { @Autowired private StringRedisTemplate redisTemplate; /** * 加鎖 * * @param key 主鍵 * @param value 當前時間+超時時間 * @return true or false */ public boolean lock(String key, String value) { Boolean lock = redisTemplate.opsForValue().setIfAbsent(key, value); if (lock != null && lock) { return true; } String currentValue = redisTemplate.opsForValue().get(key); //如果鎖過期 if (!StrUtil.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) { String oldValue = redisTemplate.opsForValue().getAndSet(key, value); if (StrUtil.isBlank(oldValue) || (!StrUtil.isEmpty(oldValue) && oldValue.equals(currentValue))) { return true; } } return false; } /** * 解鎖 * * @param key 主鍵 * @param value 當前時間+超時時間 */ public void unlock(String key, String value) { try { String currentValue = redisTemplate.opsForValue().get(key); if (!StrUtil.isEmpty(currentValue) && currentValue.equals(value)) { redisTemplate.opsForValue().getOperations().delete(key); } } catch (Exception e) { StaticLog.error("redis分布式鎖解鎖異常,{}", e.getMessage()); } }}

在上一篇文章當中的代碼中使用

public class ScheduleTask implements Runnable { private static final int TIMEOUT = 30000; private String id; private TaskService service; private String keyword; private LockUtil lockUtil; public String getId() { return id; } /** * @param id 任務ID * @param service 業務類 * @param keyword 關鍵字參數 */ public ScheduleTask(String id, TaskService service,LockUtil lockUtil, String keyword) { this.id = id; this.service = service; this.lockUtil = lockUtil; this.keyword = keyword; } @Override public void run() { String currentTime = DateUtil.now(); long time = System.currentTimeMillis() + TIMEOUT; if (lockUtil.lock(id, String.valueOf(time))) { System.out.println("ScheduleTask start taskId: " + this.id + " time: " + currentTime); try { service.work(keyword); } catch (Exception e) { StaticLog.error(e.getMessage()); } finally { lockUtil.unlock(id, String.valueOf(time)); } } }}

03

秒殺系統下的應用

這里我們來解釋一下為何在lock方法當中加上 “//如果鎖過期” 后面的代碼,我們以商品秒殺系統舉例比較好理解。

假如我們不加上這段代碼,在加鎖之后的業務流程拋出了一個異常,且這個異常我們沒有捕獲并處理,那么我們接下來的解鎖操作是不會執行的,這個時候我們的鎖就變成了死鎖,我們就可以使用getandset命令來進行解鎖,舉個?:

????????現有B商品在參加秒殺活動,假設一個購買B商品的線程發生了死鎖,此時currentValue = 1,這個時候購買B商品的兩個線程同時調用了lock方法,且value都等于2,同時這兩個線程都進入了鎖過期的判斷"if (!StringUtils.isEmpty(currentValue)&& Long.parseLong(currentValue)

以上,就是我們使用redis實現了分布式鎖。

如果你覺得小編寫的對你有用的話就扶貧一下吧,哈哈哈

總結

以上是生活随笔為你收集整理的redis分布式锁java代码_基于redis实现分布式锁的全部內容,希望文章能夠幫你解決所遇到的問題。

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