日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

SpringBoot中使用redis做分布式鎖的方法

瀏覽:8日期:2023-04-26 09:38:28

一.模擬問題

最近在公司遇到一個問題,掛號系統是做的集群,比如啟動了兩個相同的服務,病人掛號的時候可能會出現同號的情況,比如兩個病人掛出來的號都是上午2號.這就出現了問題,由于是集群部署的,所以單純在代碼中的方法中加鎖是不能解決這種情況的.下面我將模擬這種情況,用redis做分布式鎖來解決這個問題.

1.新建掛號明細表

SpringBoot中使用redis做分布式鎖的方法

2.在idea上新建項目

SpringBoot中使用redis做分布式鎖的方法

SpringBoot中使用redis做分布式鎖的方法

SpringBoot中使用redis做分布式鎖的方法

下圖是創建好的項目結構,上面那個parent項目是其他項目不用管它,和新建的沒有關系

SpringBoot中使用redis做分布式鎖的方法

3.開始創建controller,service,dao(mapper),寫好后整體結構如下

SpringBoot中使用redis做分布式鎖的方法

這里貼上service實現類的代碼,主要代碼就是這一塊:

package com.zk.service.impl; import com.zk.mapper.MzMapper;import com.zk.service.MzService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.HashMap;import java.util.Map; /** * 門診操作service實現類 * * @author zk * @date 2020-9-9 */@Servicepublic class MzServiceImpl implements MzService { @Autowired private MzMapper mzMapper; @Override public Map<String, Object> gh(String ksdm, String ysdm,String brid) { Map<String,Object> resultMap = new HashMap<>(); int ghxh = 0; //獲取當前的掛號序號 Map<String, Object> ghxhMap = mzMapper.getGhxh(ksdm,ysdm); //如果為空,說明還沒有人掛這個醫生的號,當前是一號 if(ghxhMap == null){ ghxh = 1; }else{ ghxh = (int)ghxhMap.get('GHXH'); ghxh++; } //實際場景中,先獲取到ghxh后,還會進行收費等其他操作,這里模擬一下需要耗費時間,為了方便測試出現問題,這里時間設置稍微長一點 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //新增掛號明細記錄 mzMapper.addGhmx(ksdm,ysdm,ghxh,brid); resultMap.put('code','200'); resultMap.put('msg','success'); return resultMap; }}

4.進行測試

1)清空數據庫表

2)使用postman發送post請求,假設ksdm=1表示皮膚科,ysdm=1表示醫生華佗,brbh=1表示張三,現在張三去醫院掛皮膚科華佗醫生的號,收費員就會操作系統調用上面寫的掛號接口.

SpringBoot中使用redis做分布式鎖的方法

調用成功后,看看數據庫里的數據

SpringBoot中使用redis做分布式鎖的方法

可以看到張三掛到了華佗醫生的第一個號,接著把請求參數的brbh改成2表示李四,李四也去掛華佗醫生的號

SpringBoot中使用redis做分布式鎖的方法

請求成功后查看數據庫

SpringBoot中使用redis做分布式鎖的方法

可以看到李四掛了華佗醫生的第二個號.現在就是正常的掛號,沒有出現問題.

3)postman開第二個請求窗口,兩個窗口同時去掉接口進行掛號

窗口一模擬張三掛號

SpringBoot中使用redis做分布式鎖的方法

窗口二模擬李四掛號

操作成功后看看數據庫

SpringBoot中使用redis做分布式鎖的方法

結果是張三和李四都掛到了三號,這就出現了線程安全問題.

3)使用加鎖的方式解決問題

SpringBoot中使用redis做分布式鎖的方法

方法加上鎖之后,測試確實沒有問題了,但是實際情況是集群部署的,并不是只有一個服務

4)啟動兩個服務

idea中設置允許啟動多個實例

SpringBoot中使用redis做分布式鎖的方法

修改端口號,第一個啟動的端口號是8080,這里改成8081

SpringBoot中使用redis做分布式鎖的方法

5)啟動兩個服務后再用postman去請求,張三請求8080服務接口

SpringBoot中使用redis做分布式鎖的方法

李四請求8081接口

SpringBoot中使用redis做分布式鎖的方法

兩個窗口同時請求的時候,再次出現了ghxh相同的情況,在方法上加同步鎖不能解決這個問題.

二.使用redis做分布式鎖解決問題

1.首先需要啟動一個redis,如果不知道redis怎么安裝使用的,可以看我之前寫的'redis的安裝和使用'.因為之前我在虛擬機上安裝過了redis,這里直接啟動一個單節點redis

SpringBoot中使用redis做分布式鎖的方法

2.項目的pom.xml文件引入redis依賴

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency>

3.在application.yml中配置redis

spring: redis: host: 192.168.1.6 port: 6379

4.新建redis鎖操作類

package com.zk.util; import org.apache.commons.lang3.StringUtils;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Repository; import java.util.UUID;import java.util.concurrent.TimeUnit; /** * redis鎖操作類 * * @author zk * @date 2020-9-10 */@Repositorypublic class RedisLock { private StringRedisTemplate stringredisTemplate; public RedisLock(StringRedisTemplate stringredisTemplate) { this.stringredisTemplate = stringredisTemplate; } /** * 加鎖,無阻塞 * 加鎖過程必須設置過期時間 * 如果沒有設置過期時間,手動釋放鎖的操作出現問題,那么就發生死鎖,鎖永遠不能被釋放. * 加鎖和設置過期時間過程必須是原子操作 * 如果加鎖后服務宕機或程序崩潰,來不及設置過期時間,同樣會發生死鎖. * * @param key 鎖id * @param expire 過期時間 * @return */ public String tryLock(String key, long expire) { String token = UUID.randomUUID().toString(); //setIfAbsent方法:當key不存在的時候,設置成功并返回true,當key存在的時候,設置失敗并返回false //token是對應的value,expire是緩存過期時間 Boolean isSuccess = stringredisTemplate.opsForValue().setIfAbsent(key, token, expire, TimeUnit.MILLISECONDS); if (isSuccess) { return token; } return null; } /** * 加鎖,有阻塞 * * @param name 鎖名稱 * @param expire 鎖過期時間 * @param timeout 請求超時時間 * @return */ public String lock(String name, long expire, long timeout) { long startTime = System.currentTimeMillis(); String token; do { token = tryLock(name, expire); if (token == null) { if ((System.currentTimeMillis() - startTime) > (timeout - 50)) { break; } try { //try 50 per sec Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); return null; } } } while (token == null); return token; } /** * 解鎖操作 * 解鎖必須是解除自己加上的鎖 * 試想一個這樣的場景,服務A加鎖,但執行效率非常慢,導致鎖失效后還未執行完,但這時候服務B已經拿到鎖了,這時候服務A執行完畢了去解鎖, * 把服務B的鎖給解掉了,其他服務C、D、E...都可以拿到鎖了,這就有問題了. * 加鎖的時候我們可以設置唯一value,解鎖時判斷是不是自己先前的value就行了. * * @param key * @param token * @return */ public boolean unlock(String key, String token) { //解鎖時需要先取出key對應的value進行判斷是否相等,這也是為什么加鎖的時候需要放不重復的值作為value String value = stringredisTemplate.opsForValue().get('name'); if (StringUtils.equals(value, token)) { stringredisTemplate.delete(key); return true; } return false; }}

5.修改業務操作類,用上RedisLock

package com.zk.service.impl; import com.zk.mapper.MzMapper;import com.zk.service.MzService;import com.zk.util.RedisLock;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service; import java.util.HashMap;import java.util.Map; /** * 門診操作service實現類 * * @author zk * @date 2020-9-9 */@Servicepublic class MzServiceImpl implements MzService { @Autowired private MzMapper mzMapper; @Autowired private RedisLock redisLock; @Override public Map<String, Object> gh(String ksdm, String ysdm, String brid) { Map<String, Object> resultMap = new HashMap<>(); int ghxh = 0; //加鎖操作 String token = null; token = redisLock.lock('gh', 3000,3500); try { //獲取到了鎖,執行正常業務 if (token != null) { //獲取當前的掛號序號 Map<String, Object> ghxhMap = mzMapper.getGhxh(ksdm, ysdm); //如果為空,說明還沒有人掛這個醫生的號,當前是一號 if (ghxhMap == null) { ghxh = 1; } else { ghxh = (int) ghxhMap.get('GHXH'); ghxh++; } //實際場景中,先獲取到ghxh后,還會進行收費等其他操作,這里模擬一下需要耗費時間,為了方便測試出現問題,這里時間設置稍微長一點 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //新增掛號明細記錄 mzMapper.addGhmx(ksdm, ysdm, ghxh, brid); } else { resultMap.put('code', '401'); resultMap.put('msg', '其他窗口正在操作,請稍后再試'); return resultMap; } } finally { //解鎖 if (token != null) { boolean gh = redisLock.unlock('gh', token); } } resultMap.put('code', '200'); resultMap.put('msg', 'success'); return resultMap; }}

6.再用postman開兩個窗口去請求,和上面的操作一樣,然后再看數據庫的數據

SpringBoot中使用redis做分布式鎖的方法

問題解決,不會再出現重復的ghxh.

總結

到此這篇關于SpringBoot中使用redis做分布式鎖的方法的文章就介紹到這了,更多相關SpringBoot redis分布式鎖內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品一区二区三区av| 97成人在线| 国产精品久久久久9999高清| 免费日韩av片| 免费在线成人网| 中文字幕日韩亚洲| 日韩久久99| 91精品麻豆| 麻豆一区在线| 国产suv精品一区| 亚洲综合在线电影| 久久精品动漫| 中文精品视频| 亚洲精品在线国产| 欧美视频二区| 日本不良网站在线观看| 日韩高清一区二区| 亚洲专区视频| 国产精品网站在线看| 精品国产乱码久久久久久樱花| 日韩88av| 亚洲综合中文| 欧美激情网址| 激情久久婷婷| 日本少妇一区二区| 欧美aa在线观看| 亚洲香蕉久久| 免费在线小视频| 亚洲精品福利| av高清不卡| 亚洲精品激情| 亚洲二区免费| 国产日韩欧美一区在线| 麻豆mv在线观看| 日本在线观看不卡视频| 天堂av在线| 国产极品模特精品一二| 国产精品入口久久| 美女av在线免费看| 欧美成人a交片免费看| 亚洲精品系列| 免费日韩一区二区三区| 欧美日韩精品免费观看视频完整| 国产日韩欧美中文在线| 国产一区亚洲| 欧美欧美黄在线二区| 国产一区二区三区探花| 亚洲欧洲一区二区天堂久久| 日本h片久久| 国产精品88久久久久久| 国内精品麻豆美女在线播放视频| 亚州av一区| 鲁大师精品99久久久| 国产精品videossex| 日韩中文字幕区一区有砖一区 | 在线观看一区| 性欧美长视频| 日韩中文字幕1| 久热re这里精品视频在线6| 国内精品福利| 日产精品一区二区| 精品国产一区二| 97人人精品| 亚洲午夜视频| 久久福利精品| 日韩精品欧美大片| 欧美精品影院| 精品少妇一区| 久久精品影视| aa亚洲婷婷| 日本中文字幕一区二区视频| 亚洲精品高潮| 国产情侣久久| 亚洲精品福利电影| 米奇777超碰欧美日韩亚洲| 亚洲国产一区二区在线观看 | aa亚洲婷婷| 日韩毛片一区| 国产精品久av福利在线观看| 91综合久久爱com| 里番精品3d一二三区| 97国产成人高清在线观看| 国产拍在线视频| 久久性天堂网| 国产乱论精品| 精品午夜久久| 久久久噜噜噜| 亚洲精品少妇| caoporn视频在线| 在线午夜精品| 91亚洲成人| 最新亚洲国产| 人人精品亚洲| 国产亚洲第一伦理第一区| 国产91精品对白在线播放| 日韩黄色av| 婷婷国产精品| 国产欧美日韩精品高清二区综合区 | 国产成人免费| 亚州精品视频| 成人啊v在线| 88久久精品| 红桃视频国产精品| 精品久久免费| 欧美一区自拍| 日韩精品一级中文字幕精品视频免费观看 | 欧美丰满日韩| 日本aⅴ免费视频一区二区三区| 伊人久久国产| 国产精品亚洲欧美一级在线| 亚洲乱码视频| 中文欧美日韩| 欧美日韩在线二区| 成人在线免费观看91| 亚洲午夜久久| 亚洲自拍另类| 久久精品国内一区二区三区水蜜桃| 国产精品v一区二区三区| 亚洲理论在线| 神马日本精品| 91一区二区三区四区| 中文久久精品| 久久视频国产| 欧美精品日日操| 久久青青视频| 欧美成人综合| 精品三区视频| 亚洲精品精选| 久久久久免费av| 欧美在线看片| 日韩av中文字幕一区二区三区| 日韩不卡一区| 欧美女激情福利| 久久精品亚洲欧美日韩精品中文字幕| 国产精品xx| 久久中文字幕av| 中文字幕一区二区三区在线视频| 精品无人区麻豆乱码久久久| 美女精品视频在线| 久久精品国产久精国产| 亚洲福利国产| 欧美日韩一区二区三区四区在线观看 | 精品视频网站| 精品国产aⅴ| 日本免费久久| 亚洲国产成人精品女人| 男人操女人的视频在线观看欧美| 91精品二区| 日韩精品一级| 国产+成+人+亚洲欧洲在线| 中文字幕在线免费观看视频| 久久香蕉精品香蕉| 视频小说一区二区| 亚洲精品一级| sm捆绑调教国产免费网站在线观看| 日韩国产网站| 亚洲尤物av| 亚洲最新无码中文字幕久久 | 国产精品毛片| 日韩精品一二三| 国产一区二区三区久久| 黄色av一区| 美腿丝袜在线亚洲一区| 国产精品亚洲综合久久| 欧美日韩一区二区三区视频播放| 香蕉久久国产| 国产一区调教| 欧美一级一区| 欧美日韩国产高清| 精品久久视频| 日韩av网站在线免费观看| 日韩视频网站在线观看| 色狠狠一区二区三区| 亚洲成a人片| 欧美精品国产一区| 99国产精品久久久久久久| 久久精品九色| 日本精品另类| 欧美日韩视频| 欧美a在线观看| 亚洲久久视频| 亚洲免费高清| 九九在线精品| 日韩免费小视频| 久久av导航| 日韩国产欧美三级| 一区二区三区四区精品视频| 极品裸体白嫩激情啪啪国产精品| 精品国产乱码久久久| 亚洲在线网站| 日韩 欧美一区二区三区| 美女日韩在线中文字幕| 在线视频亚洲| 国精品一区二区| 九色精品91| 美女精品在线| 青青国产精品| 欧美黑人巨大videos精品| 欧美a在线观看| 成人影视亚洲图片在线|