【分散式鎖】SpringBoot中使用Redisson
阿新 • • 發佈:2020-11-27
Redisson 是基於Redis實現的高效能的同步、加鎖的的開源專案。
Redisson的開源地址,redisson-spring-boot-starter的開源地址。
筆者使用版本 3.14.0,快速上手。
1.1新增redisson-spring-boot-starter
maven dependency
<!-- redisson分散式鎖 --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.14.0</version> </dependency>
1.2 如果是單機版本,只需要配置 redis 的配置就行了,其他什麼都不用。
# redis 配置
spring: redis: port: 6379 host: 127.0.0.1 password: 000000 database: 0 timeout: 2000
1.3 測試一下是否有效。
package com.qs.monitor.controller.utils; import com.qs.monitor.common.JsonResult; import com.qs.monitor.controller.BaseController; importcom.qs.monitor.service.UtilsService; import eu.bitwalker.useragentutils.Browser; import eu.bitwalker.useragentutils.OperatingSystem; import eu.bitwalker.useragentutils.UserAgent; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.web.bind.annotation.*;import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.concurrent.TimeUnit; /** * @author zhaww * @date 2020/9/24 * @Description . */ @RestController @RequestMapping("/utils") public class UtilsController extends BaseController {
// redisson 鎖 @Resource private RedissonClient redissonClient; @RequestMapping(value = "test", method = RequestMethod.GET) public JsonResult test() { // test 為鎖的主鍵,根據情況可使用 UUID RLock rLock = redissonClient.getLock("test"); System.out.println(Thread.currentThread().getName() + " 進入方法"); //如果鎖已經被使用,則會一直在等著鎖被釋放 rLock.lock(); // 佔用鎖後,10秒後自動釋放 // rLock.lock(10, TimeUnit.SECONDS); try { System.out.println(Thread.currentThread().getName() + " 開始執行"); Thread.sleep(8000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println(Thread.currentThread().getName() + " 執行完成,解鎖"); if (rLock.isLock()) {
rLock.unlock();
} } System.out.println(Thread.currentThread().getName() + " 返回結果"); return success(); } }
上面這種加鎖方式,如果出現死鎖,就所有的訪問都無法進行了。所以推薦使用下面這種加鎖方式!
package com.qs.monitor.controller.utils; import com.qs.monitor.common.JsonResult; import com.qs.monitor.controller.BaseController; import com.qs.monitor.service.UtilsService; import eu.bitwalker.useragentutils.Browser; import eu.bitwalker.useragentutils.OperatingSystem; import eu.bitwalker.useragentutils.UserAgent; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.concurrent.TimeUnit; /** * @author zhaww * @date 2020/9/24 * @Description . */ @RestController @RequestMapping("/utils") public class UtilsController extends BaseController { // redisson 鎖 @Resource private RedissonClient redissonClient; @RequestMapping(value = "/test", method = RequestMethod.GET) public JsonResult test() { RLock rLock = redissonClient.getLock("test"); System.out.println(Thread.currentThread().getName() + " 進入方法"); Boolean isLock; try { //最多等待10秒拿鎖,如果佔用鎖後,10秒後自動釋放 isLock = rLock.tryLock(10,10, TimeUnit.SECONDS); if (isLock) { try { System.out.println(Thread.currentThread().getName() + " 開始執行"); Thread.sleep(8000); } finally { System.out.println(Thread.currentThread().getName() + " 執行完成,解鎖"); if (rLock.isLocked()) { rLock.unlock(); } } } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 返回結果"); return null; } }
1.4 叢集配置。(我嘗試使用最新的文件中的配置方法,但是報 ymal 格式異常)所以只能自己重寫配置類了
package com.qs.monitor.config; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import java.io.IOException; /** * @author zhaww * @date 2020/11/26 * @Description .Redisson配置資訊 */ @Configuration public class RedissonConfig { /** * redis 地址 */ @Value("${spring.redis.redisson.address}") private String address; /** * 叢集版配置 * @return */ @Bean RedissonClient redissonClusterConfig() { Config config = new Config(); //更多配置參考官網,不過多介紹 config.useClusterServers() .addNodeAddress(address) .addNodeAddress(address); return Redisson.create(config); } }