分布式锁: Distributed-Lock

一、简介

Distributed-Lock为解决分布式系统中资源争夺而生。在当前分布式、微服务架构盛行的年代,多个服务可能会对第一个资源进行抢夺,如果不加以控制,可能导致无法想象的后果,或者有一些操作不可以同时多次操作。

​ 1、底层存储目前只支持三种:Redis、Zookeeper、Mysql,推荐使用Redis。

​ 2、支持锁超时自动释放锁,防止死锁,同时也是可重入锁。

​ 3、使用简单方便,侵入式较低,代码只需要一个注解 @Lock

​ 4、锁的资源ID以及请求标识都支持 Spel表达式

二、使用

1、添加依赖

github地址:https://github.com/wens1121/distributed-lock

下载源码后进行打包:mvn install

引入依赖

<dependency>
  <groupId>com.distributed-lock</groupId>
  <artifactId>lock-spring-boot-starter</artifactId>
  <version>1.0.1</version>
</dependency>

2、配置存储依赖

​ 指定存储依赖

spring:
	dispers-lock:
		storage: redis/zookeeper/mysql

默认是可以不做配置的,三种方式是有优先级的,并且会根据依赖环境进行自动装配。

优先级排序:
r e d i s > z o o k e e p e r > m y s q l redis>zookeeper>mysql redis>zookeeper>mysql

3、使用环境说明

Redis

依赖RedisTemplate 如果springboot中没有配置RedisTemplate,则不可使用

Zookeeper

​ 依赖pom

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.11.0</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.11.0</version>
    <scope>provided</scope>
</dependency>

​ 配置

spring:
  dispers-lock:
    storage: zookeeper
    zookeeper-config:
      ipPorts: 127.0.0.1:2181

Mysql

依赖DataSource,如果没有dataSource则不会加载,多数据源情况下通过配置可以指定数据源。

详细配置可以看 LockConfig

3、代码

使用是特别方便的,只需要关注 @Lock 注解

@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lock {
    /** 锁的key */
    String key() ;

    /** 锁的请求ID 值为-1,则使用UUID*/
    String id() default "'0'";

    /** 超时时间 */
    long timeout() default 1;

    /** 时间单位 */
    TimeUnit unit() default TimeUnit.HOURS;

    /** 锁类型,默认方法结束后释放锁 */
    LockTypeEnum lockType() default LockTypeEnum.AUTO_LOCK;
}
/**
 * @Author 温少
 * @Description  说明: 只加锁,方法执行前加锁
 * @Date 2020/9/11 3:57 下午
 * @Param  * @param
 * @return void
 **/
@Lock(key = "'test'",id = "#user.name + '_aaaaa'",lockType = LockTypeEnum.LOCK)
public void test(User user){
    System.out.println("------------>>>>>>>>"+user);
}


/**
 * @Author 温少
 * @Description  说明: 只解锁,方法执行结束进行解锁
 * @Date 2020/9/11 3:57 下午
 * @Param  * @param
 * @return void
 **/
@Lock(key = "test",lockType = LockTypeEnum.UNLOCK)
public void test2(){
    System.out.println("------------>>>>>>>>");
}


/**
 * @Author 温少
 * @Description  说明: 自动加解锁,方法执行前加锁,执行完解锁
 * @Date 2020/9/11 3:57 下午
 * @Param  * @param
 * @return void
 **/
@Lock(key = "'data'",id = "#id" ,lockType = LockTypeEnum.AUTO_LOCK)
public void test3(String id){
    System.out.println("-----------------"+id);
}

三、问题

1、在AOP中获取方法的参数列表名称为空,导致空指针异常

在springboot 2.0之前,动态代理默认使用的是jdk动态代理,之后默认使用的是cglib动态代理。使用jdk动态代理是无法获取到方法的参数列表的,所以要修改配置,改为强制使用cglib代理

spring:
  aop:
      proxy-target-class: true
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐