Java小强个人技术博客站点    手机版
当前位置: 首页 >> 开源 >> Lock4J分布式锁

Lock4J分布式锁

5170 开源 | 2024-2-7

简介

lock4j是一个分布式锁组件,其提供了多种不同的支持以满足不同性能和环境的需求。

立志打造一个简单但富有内涵的分布式锁组件。

特性

简单易用,功能强大,扩展性强。

支持redission,redisTemplate,zookeeper。可混用,支持扩展。


lock4j.jpg


开源地址:https://gitee.com/baomidou/lock4j 


引入相关依赖(支持同时存在,不同方法不同锁实现)。

<dependencies>
    <!--若使用redisTemplate作为分布式锁底层,则需要引入-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
        <version>${latest.version}</version>
    </dependency>
    <!--若使用redisson作为分布式锁底层,则需要引入-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
        <version>${latest.version}</version>
    </dependency>
    <!--若使用zookeeper作为分布式锁底层,则需要引入-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>lock4j-zookeeper-spring-boot-starter</artifactId>
        <version>${latest.version}</version>
    </dependency>
</dependencies>


Spring配置Reids连接,zookeeper不再介绍

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;
import com.baomidou.lock.executor.LockExecutor;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Lock4j {
    // 需要锁住的Key的名称
    String name() default "";
    // 自定义执行器
    Class<? extends LockExecutor> executor() default LockExecutor.class;
    // 需要锁住的Key的名称,可以多个
    String[] keys() default {""};
    // 锁过期时间,防止死锁
    long expire() default -1L;
    // 排队时长,超过这个时才就退出排队,抛出获取锁超时异常
    long acquireTimeout() default -1L;
    // 是否自动释放锁
    boolean autoRelease() default true;
}


在需要分布式的地方使用Lock4j注解

@Service
public class DemoService {
    //默认获取锁超时3秒,30秒锁过期
    @Lock4j
    public void simple() {
        //do something
    }
    //完全配置,支持spel
    @Lock4j(keys = {"#user.id", "#user.name"}, expire = 60000, acquireTimeout = 1000)
    public User customMethod(User user) {
        return user;
    }
}



高级使用

配置全局默认的获取锁超时时间和锁过期时间

lock4j:
  acquire-timeout: 3000 #默认值3s,可不设置
  expire: 30000 #默认值30s,可不设置
  primary-executor: com.baomidou.lock.executor.RedisTemplateLockExecutor #默认redisson>redisTemplate>zookeeper,可不设置
  lock-key-prefix: lock4j #锁key前缀, 默认值lock4j,可不设置

acquire-timeout 可以理解为排队时长,超过这个时才就退出排队,抛出获取锁超时异常。

expire 锁过期时间 。 主要是防止死锁。 建议估计好你锁方法运行时常,正常没有复杂业务的增删改查最多几秒,留有一定冗余,10秒足够。 我们默认30秒是为了兼容绝大部分场景。


自定义执行器

@Service
public class DemoService {
    //可在方法级指定使用某种执行器,若自己实现的需要提前注入到Spring。
    @Lock4j(executor = RedissonLockExecutor.class)
    public Boolean test() {
        return "true";
    }
}


自定义锁key生成器

默认的锁key生成器为 com.baomidou.lock.DefaultLockKeyBuilder

@Component
public class MyLockKeyBuilder extends DefaultLockKeyBuilder {
    @Override
    public String buildKey(MethodInvocation invocation, String[] definitionKeys) {
        String key = super.buildKey(invocation, definitionKeys);
        // do something
        return key;
    }
}


自定义锁获取失败策略

默认的锁获取失败策略为 com.baomidou.lock.DefaultLockFailureStrategy

@Component
public class MyLockFailureStrategy implements LockFailureStrategy {
    @Override
    public void onLockFailure(String key, long acquireTimeout, int acquireCount) {
        // write my code
    }
}


手动上锁解锁

@Service
public class ProgrammaticService {
    @Autowired
    private LockTemplate lockTemplate;
    public void programmaticLock(String userId) {
        // 各种查询操作 不上锁
        // ...
        // 获取锁
        final LockInfo lockInfo = lockTemplate.lock(userId, 30000L, 5000L, RedissonLockExecutor.class);
        if (null == lockInfo) {
            throw new RuntimeException("业务处理中,请稍后再试");
        }
        // 获取锁成功,处理业务
        try {
            System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName() + " , counter:" + (counter++));
        } finally {
            //释放锁
            lockTemplate.releaseLock(lockInfo);
        }
        //结束
    }
}


指定时间内不释放锁(限流)

@Service
public class DemoService {
    // 用户在5秒内只能访问1次
    @Lock4j(keys = {"#user.id"}, acquireTimeout = 0, expire = 5000, autoRelease = false)
    public Boolean test(User user) {
        return "true";
    }
}


END

推荐您阅读更多有关于“ redis zookeeper Redisson Lock4J ”的文章

上一篇:SpringBoot集成Redisson实现接口限流 下一篇:FastJSON错误Could not read JSON: Unrecognized field

猜你喜欢

发表评论: