java 實現開箱即用基於 redis 的分散式鎖

老馬嘯西風發表於2022-12-14

專案簡介

lock 為 java 設計的分散式鎖,開箱即用,縱享絲滑。

開源地址:https://github.com/houbb/lock

目的

  • 開箱即用,支援註解式和過程式呼叫
  • 基於 redis 的分散式鎖
  • 內建支援多種 redis 的整合方式
  • 漸進式設計,可獨立於 spring 使用
  • 整合 spring
  • 整合 spring-boot

快速開始

需要

jdk1.7+

maven 3.x+

maven 引入

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>lock-core</artifactId>
    <version>1.3.0</version>
</dependency>

入門例子

基於本地 redis 的測試案例。

public void helloTest() {
    ILock lock = LockBs.newInstance();
    String key = "ddd";
    try {
        // 加鎖
        lock.tryLock(key);
        System.out.println("業務處理");
    } catch (Exception e) {
        throw new RuntimeException(e);
    } finally {
        // 釋放鎖
        lock.unlock(key);
    }
}

配置化

為了便於擴充,LockBs 的配置支援自定義:

LockBs.newInstance()
        .id(Ids.uuid32())   //id 生成策略
        .cache(JedisRedisServiceFactory.pooled("127.0.0.1", 6379)) //快取策略
        .lockSupport(new RedisLockSupport())    // 鎖實現策略
        .lockKeyFormat(new LockKeyFormat())     // 針對 key 的格式化處理策略
        .lockReleaseFailHandler(new LockReleaseFailHandler())   //釋放鎖失敗處理
        ;

整合 spring

maven 引入

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>lock-spring</artifactId>
    <version>1.3.0</version>
</dependency>

指定 bean 使用

啟用分散式鎖

@EnableLock 啟用分散式鎖。

@EnableRedisConfig 啟用 redis 的預設配置。

@Configurable
@ComponentScan(basePackages = "com.github.houbb.lock.test.service")
@EnableLock
@EnableRedisConfig
public class SpringConfig {
}

EnableLock 註解說明,和引導類對應:

public @interface EnableLock {

    /**
     * 唯一標識生成策略
     * @return 結果
     */
    String id() default "lockId";

    /**
     * 快取實現策略 bean 名稱
     *
     * 預設引入 redis-config 中的配置
     *
     * @return 實現
     */
    String cache() default "springRedisService";

    /**
     * 加鎖 key 格式化策略
     * @return 策略
     */
    String lockKeyFormat() default "lockKeyFormat";

    /**
     * 鎖釋放失敗處理類
     * @return 結果
     */
    String lockReleaseFailHandler() default "lockReleaseFailHandler";

}

其中 springRedisService 使用的是 redis-config 中的實現。

對應註解 @EnableRedisConfig,redis 的配置資訊如下:

配置說明預設值
redis.addressredis 地址127.0.0.1
redis.portredis 埠6379
redis.passwordredis 密碼

使用 LockBs

我們可以直接 LockBs 的引導類,這種適合一些更加靈活的場景。

@ContextConfiguration(classes = SpringConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringServiceRawTest {

    @Autowired
    private UserService userService;

    @Autowired
    private LockBs lockBs;

    @Test
    public void queryLogTest() {
        final String key = "name";
        try {
            lockBs.tryLock(key);
            final String value = userService.rawUserName(1L);
        } catch (Exception exception) {
            throw new RuntimeException(exception);
        } finally {
            lockBs.unlock(key);
        }
    }

}

aop 註解使用

指定方法註解

當然,我們可以在方法上直接指定註解 @Lock,使用更加方便。

直接使用,AOP 切面生效即可。

@Service
public class UserService {

    @Lock
    public String queryUserName(Long userId) {
    }

    @Lock(value = "#user.name")
    public void queryUserName2(User user) {
    }
}

@Lock 屬性說明,value 用於指定 key,支援 SPEL 表示式。

其他屬性,和引導類的方法引數一一對應。

public @interface Lock {

    /**
     * 快取的 key 策略,支援 SpEL
     * @return 結果
     */
    String value() default "";

    /**
     * 時間單位
     * @return 單位
     */
    TimeUnit timeUnit() default TimeUnit.SECONDS;

    /**
     * 等待鎖時間
     * @return 等待鎖時間
     */
    long waitLockTime() default 10;

    /**
     * 業務加鎖時間
     * @return 加鎖時間
     */
    long lockTime() default 60;

}

spring boot 整合

maven 引入

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>lock-springboot-starter</artifactId>
    <version>1.3.0</version>
</dependency>

使用

同 spring

後期 Road-MAP

  • [ ] 支援鎖的可重入

持有鎖的執行緒可以多次獲取鎖

  • [x] 分散式鎖註解支援

擴充閱讀

Redis 分散式鎖

java 從零實現 redis 分散式鎖

快取相關工具

cache: 手寫漸進式 redis

common-cache: 通用快取標準定義

redis-config: 相容各種常見的 redis 配置模式

lock: 開箱即用的分散式鎖

resubmit: 防重複提交

rate-limit: 限流

相關文章