切換語言為:簡體

一個強大的分散式鎖框架——Lock4j

  • 爱糖宝
  • 2024-07-11
  • 2068
  • 0
  • 0

一、簡介

Lock4j是一個分散式鎖元件,它提供了多種不同的支援以滿足不同效能和環境的需求,基於Spring AOP的宣告式和程式設計式分散式鎖,支援RedisTemplate、Redisson、Zookeeper

二、特性

  • 簡單易用,功能強大,擴充套件性強。

  • 支援redission, redisTemplate, zookeeper,可混用,支援擴充套件。

Gitee:gitee.com/baomidou/lo…

三、使用前準備

3.1 引入依賴

<!-- Lock4j -->
<!-- 若使用redisTemplate作為分散式鎖底層,則需要引入 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
    <version>2.2.4</version>
</dependency>
<!-- 若使用redisson作為分散式鎖底層,則需要引入 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
    <version>2.2.4</version>
</dependency>


3.2 新增redis配置

spring:
  redis:
    database: 0
    # Redis伺服器地址 寫你的ip
    host: 127.0.0.1
    # Redis伺服器連線埠
    port: 6379
    # Redis伺服器連線密碼(預設為空)
    password:
    # 連線池最大連線數(使用負值表示沒有限制  類似於mysql的連線池
    jedis:
      pool:
        max-active: 200
        # 連線池最大阻塞等待時間(使用負值表示沒有限制) 表示連線池的連結拿完了 現在去申請需要等待的時間
        max-wait: -1
        # 連線池中的最大空閒連線
        max-idle: 10
        # 連線池中的最小空閒連線
        min-idle: 0
    # 連線超時時間(毫秒) 去連結redis服務端
    timeout: 6000


四、註解屬性介紹

package com.baomidou.lock.annotation;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Lock4j {
    String name() default "";

    Class<? extends LockExecutor> executor() default LockExecutor.class;

    String[] keys() default {""};

    long expire() default -1L;

    long acquireTimeout() default -1L;

    boolean autoRelease() default true;
}


@Lock4j註解屬性 說明
name 需要鎖住的key名稱
executor 可以透過該引數設定自定義特定的執行器
keys 需要鎖住的keys名稱,可以是多個
expire 鎖過期時間,主要是用來防止死鎖
acquireTimeout 可以理解為排隊等待時長,超過這個時長就退出排隊,並排除獲取鎖超時異常
autoRelease 是否自動釋放鎖,預設是true

五、簡單使用

@RestController
@RequestMapping("/mock")
public class MockController {

    @GetMapping("/lockMethod")
    @Lock4j(keys = {"#key"}, acquireTimeout = 1000, expire = 10000)
    public Result lockMethod(@RequestParam String key) {
        ThreadUtil.sleep(5000);
        return Result.OK(key);
    }
}


開啟瀏覽器視窗,重複重新整理訪問:http://localhost:8080/mock/lockMethod?key=123

成功獲得鎖訪問結果:

{
    "success": true,
    "message": "操作成功!",
    "code": 200,
    "result": "123",
    "timestamp": 1678866083211
}


搶佔不到鎖,Lock4j會丟擲com.baomidou.lock.exception.LockFailureException: request failed,please retry it.異常,透過全域性異常處理返回如下結果:

{
    "success": false,
    "message": "操作失敗,request failed,please retry it.",
    "code": 500,
    "result": null,
    "timestamp": 1678866034929
}


六、高階使用

6.1 自定義執行器Exector

/**
 * 自定義分散式鎖執行器
 *
 * @author: austin
 * @since: 2023/3/15 15:45
 */
@Component
public class CustomRedissonLockExecutor extends AbstractLockExecutor {
    
    @Override
    public Object acquire(String lockKey, String lockValue, long expire, long acquireTimeout) {
        return null;
    }

    @Override
    public boolean releaseLock(String key, String value, Object lockInstance) {
        return false;
    }
}


在註解上直接指定特定的執行器:@Lock4j(executor = CustomRedissonLockExecutor.class)

6.2 自定義分散式鎖key生成器

/**
 * 自定義分散式鎖key生成器
 *
 * @author: austin
 * @since: 2023/3/15 15:46
 */
@Component
public class CustomKeyBuilder extends DefaultLockKeyBuilder {

    public CustomKeyBuilder(BeanFactory beanFactory) {
        super(beanFactory);
    }
}


6.3 自定義搶佔鎖失敗執行策略

/**
 * 自定義搶佔鎖失敗執行策略
 *
 * @author: austin
 * @since: 2023/3/15 15:49
 */
@Component
public class GrabLockFailureStrategy implements LockFailureStrategy {

    @Override
    public void onLockFailure(String key, Method method, Object[] arguments) {

    }
}


預設的鎖獲取失敗策略為 com.baomidou.lock.DefaultLockFailureStrategy.

6.4 手動加鎖釋放鎖

@Service
public class LockServiceImpl implements LockService {

    @Autowired
    private LockTemplate lockTemplate;

    @Override
    public void lock(String resourceKey) {

        LockInfo lock = lockTemplate.lock(resourceKey, 10000L, 2000L, CustomRedissonLockExecutor.class);
        if (lock == null) {
            // 獲取不到鎖
            throw new FrameworkException("業務處理中,請稍後再試...");
        }
        // 獲取鎖成功,處理業務
        try {
            doBusiness();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lockTemplate.releaseLock(lock);
        }
    }

    private void doBusiness() {
        // TODO 業務執行邏輯
    }
}

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.