1. 程式人生 > 實用技巧 >【分散式鎖】SpringBoot中使用Redisson

【分散式鎖】SpringBoot中使用Redisson

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;
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() { // 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);
    }
}