[框架系列]-[通用lock框架]集成及具体配置使用

发布时间:2024年01月23日

目录

一:框架集成

1.添加pom依赖

2.开启lock配置

二:配置详细介绍

1.配置清单

2.具体配置介绍

(1)implementer

(2)type

(3)transactionStrategy

(4)lockFailStrategy

(5)lockExceptionStrategy

(6)releaseTimeoutStrategy

三:CUSTOMER的SPI扩展示例

1.SPI扩展点

2.使用示例

四:代码示例

1.代码方式

2:注解方式示例

(1).方法头部同时存在@Transactional及@Lock时

(2).@LockKey的使用

(3).快捷注解的使用

4().自定义快速失败时,抛出的异常类型及异常信息(可单独设置)

(5).定制上锁失败策略


一:框架集成

1.添加pom依赖

<dependency>

???<groupId>com.ty</groupId>

???<artifactId>ty-framework-lock-starter</artifactId>

???<version>0.2.9</version>

</dependency>

2.开启lock配置

目前分布式锁仅支持redis实现

application.yml示例:

application:

??lock:

????enable:?true

spring:

??redis:

????database:?3

????cluster:

??????nodes:?192.168.xx.xxx:6479,192.168.xx.xxx:6479,192.168.xx.xxx:6479

????password:?12345678

application.properties示例:

application.lock.enable=true

#redis集群版配置示例,其他版本配置具体见Spring redis相关配置

spring.redis.database=3

spring.redis.cluster.nodes=192.168.xx.xxx:6479,192.168.xx.xxx:6479,192.168.xx.xxx:6479

spring.redis.password=12345678

如遇到集成问题,可联系@苏友良

二:配置详细介绍

1.配置清单

配置名

配置简介

默认值

作用域

其他

enable

是否开启

Boolean.FALSE

全局

使用需开启此配置

implementer

lock厂商实现类型

LockImplementer.REDIS

全局及注解

redis实现

type

lock 的类型

LockType.Reentrant

全局及注解

keys

自定义业务key(支持SpingEL)

注解

系统会按照${name}:${key1}:...:${keyN}:${@LockKey1}:...:${@LockKeyN}的方式拼接,作为lock的key

特殊的:当name,keys以及注解@LockKey都为空时,系统默认使用方法的全限定类名作为key(不推荐使用此方式)

name

锁的名称

注解

系统会按照${name}:${key1}:...:${keyN}:${@LockKey1}:...:${@LockKeyN}的方式拼接,作为lock的key

特殊的:当name,keys以及注解@LockKey都为空时,系统默认使用方法的全限定类名作为key(不推荐使用此方式)

supportTransaction

是否支持上下文感知

Boolean.TRUE

全局及注解

withLocalCache

是否支持本地lock二级缓存

Boolean.FALSE

全局及注解

transactionStrategy

仅开启supportTransaction生效

LockTransactionStrategy.WARMING

全局

打warm日志

waitTime

等待时间

2s

全局及注解

leaseTime

等待时间

60s

全局及注解

此参数在Lock官方定义中不生效,可通过自定义LockAdapter使用该参数。redis实现中默认此参数不生效(自动续期机制),如方言需使用此参数参考:cn.techwolf.blue.usl.framework.lock.factory.support.RedissonLockAdapterFactory

lockFailStrategy

加锁失败的处理策略

FailOnLockStrategy.FAIL_FAST

全局及注解

快速失败

exceptionOnLockStrategy

加锁异常的处理策略

ExceptionOnLockStrategy.THROW_EXCEPTION

全局及注解

抛出异常

releaseTimeoutStrategy

释放锁时异常的处理策略

ReleaseTimeoutStrategy.FAIL_FAST

全局及注解

快速失败

exceptionClass

获取锁失败时,报错的异常类型

LockException

全局及注解

获取锁失败时,报错的异常类型
1.仅当LockFailStrategy.FAIL_FAST或者ReleaseTimeoutStrategy.FAIL_FAST 生效 此处设置二者都会生效
2.优先级:注解exceptionClass>lockConfig exceptionClass>系统默认
3.示例:cn.techwolf.blue.usl.framework.common.exception.FrameworkException
4.注意:必须是RuntimeException的子类

exceptionMsg

获取锁失败时,报错的错误信息

Failed to acquire Lock(%s) with timeout(%d ms)

全局及注解

仅当LockFailStrategy.FAIL_FAST或者ReleaseTimeoutStrategy.FAIL_FAST生效此处设置二者都会生效
优先级:注解exceptionClass>lockConfig exceptionClass>系统默认

customLockFailStrategy定制的加锁失败的处理策略注解用户指定,定义的方法参数需要和注解所在的方法参数保持一致
此方式与lockFailStrategy中的CUSTOM不同点在于:此方式可对方法具体参数做定制化的处理策略,
后者更适合做全局的默认处理
customReleaseTimeout
Strategy
定制的释放锁时异常的处理策略注解

用户指定,定义的方法参数需要和注解所在的方法参数保持一致

此方式与releaseTimeoutStrategy中的CUSTOM不同点在于:此方式可对方法具体参数做定制化的处理策略,后者更适合做全局的默认处理

注解配置优先级大于全局配置。仅当注解没有配置才会使用全局配置

2.具体配置介绍
(1)implementer

提供的厂商实现:

  • JVM 本地JVM实现
  • REDIS?redis实现?
  • ZOOKEEPER?zookeeper实现
  • ETCD?etcd实现
  • MYSQL mysql实现

具体见:cn.techwolf.blue.usl.framework.lock.config.LockConfig.LockImplementer

(2)type

lock厂商实现类型:

  • Reentrant?可重入锁

  • Fair 公平锁
  • Read 读锁
  • Write 写锁
  • Spin 自旋锁

具体见:cn.techwolf.blue.usl.framework.lock.enums.LockType

(3)transactionStrategy

当lock存在于事务上下文中的策略(仅开启supportTransaction生效):

  • WAARMING??打warming日志
  • FORBIDDEN 禁止,会抛出异常阻断业务逻辑
  • THREAD_SAFE 保证多线程访问安全,unlock会在事务完成后再提交。缺点:会使lock的作用域膨胀。直至上下文事务完成
(4)lockFailStrategy

加锁失败的处理策略:

  • NO_OPERATION:继续执行业务逻辑,不做任何处理
  • FAIL_FAST:快速失败
  • KEEP_ACQUIRE:一直阻塞,直到获得锁,在太多的尝试后,仍会报错
  • CUSTOMER: 自定义,用于全局默认处理
(5)lockExceptionStrategy

加锁异常的处理策略:

  • THROW_EXCEPTION:抛出异常
  • CUSTOMER:自定义,用于全局默认处理

(6)releaseTimeoutStrategy

释放锁时报错的处理策略:

  • NO_OPERATION:继续执行业务逻辑,不做任何处理
  • FAIL_FAST:快速失败,可自定义异常类及报错信息
  • CUSTOMER: 自定义,用于全局默认处理

三:CUSTOMER的SPI扩展示例

1.SPI扩展点

以上的策略中,lockFailStrategy,lockExceptionStrategy,releaseTimeoutStrategy 都提供了CUSTOMER的的策略,框架通过java的SPI机制,将对应的用户自实现的策略加载

策略点

策略名

具体配置名

扩展定义接口

加锁失败的处理策略lockFailStrategyCUSTOMERcn.techwolf.blue.usl.framework.lock.handler.lock.ExceptionOnLockCustomerHandler
加锁异常的处理策略lockExceptionStrategyCUSTOMERcn.techwolf.blue.usl.framework.lock.handler.lock.FailOnLockCustomerHandler
加锁释放锁异常的处理策略releaseTimeoutStrategyCUSTOMERcn.techwolf.blue.usl.framework.lock.handler.release.ReleaseTimeoutCustomerHandler
2.使用示例

这里以ExceptionOnLockCustomerHandler 作为示例

(1)在resources文件夹下创建文件夹META-INF/services

(2)在META-INF/services中添加file,名称为扩展的Handler的全限定类名

(3)文件中填写自己基于定义的接口的实现类的全限定类名

自定义处理策略加载后,如果需要指定为全局,需要在全局配置中指定定位的策略名的配置为CUSTOMER即可开启,方法级(或者注解)同理

注意:无论是全局还是注解的方法级,一旦指定以上策略的配置为CUSTOMER,则系统运行时必须存在对应的实现类,否则报错。不同的是,全局级配置报错将导致项目无法启动

四:代码示例

1.代码方式

@Autowired

LockRegistry lockRegistry;

public?void?testApi()?throws?Exception {

????Lock lock = lockRegistry.obtain("aaa");

????try?{

????????boolean?b = lock.tryLock(2, TimeUnit.SECONDS);

????????if?(b){

????????????//do your business code

????????}

????}finally?{

????????lock.unlock();

????}

}

2:注解方式示例
(1).方法头部同时存在@Transactional及@Lock时

@Lock(waitTime =?10, keys = {"#param"}, timeUnit = TimeUnit.SECONDS, lockFailStrategy = FailOnLockStrategy.FAIL_FAST)

@Transactional

public?String getValue(String param)?throws?Exception {

????if?("sleep".equals(param)) {//线程休眠或者断点阻塞,达到一直占用锁的测试效果

????????Thread.sleep(100?*?10);

????}

????return?"success";

}

其中:当方法存在@Transactional时,@Lock方法将在 @Transactional之后执行,即:事务开启前上锁,事务关闭后解锁。与两个注解的上下顺序无关

(2).@LockKey的使用

@Lock(keys = {"#userId"})

public?String getValue(String userId,?@LockKey?Integer id)?throws?Exception {

????Thread.sleep(60?*?10);

????return?"success";

}

按照${name}:${key1}:...:${keyN}:${@LockKey1}:...:${@LockKeyN}的拼接逻辑? 以上示例的key:${userId}:${id}

(3).快捷注解的使用

@FailFastLock(keys = {"#user.id"})

public?String getValueWithFailFastLock(User user) {

????try?{

????????Thread.sleep(1000);

????}?catch?(InterruptedException e) {

????????e.printStackTrace();

????}

????return?"success";

}

@LocalLock(keys = {"#user.id"})

public?String getValueWithLocalLock(User user) {

????try?{

????????Thread.sleep(1000);

????}?catch?(InterruptedException e) {

????????e.printStackTrace();

????}

????return?"success";

}

@FailFastLock 快速失败的锁,无需设置等待时间,等待时间为0s

@LocalLock 本地jvm实现的锁

4().自定义快速失败时,抛出的异常类型及异常信息(可单独设置)

@Lock(name =?"foo-service", waitTime =?1, exceptionClass =?"techwolf.blue.usl.framework.springboot.lock.test.customer.exception.CustomerException",exceptionMsg =?"我是注解自定义异常信息")

public?void?foo10() {

????try?{

????????log.info("acquire lock");

????????TimeUnit.SECONDS.sleep(2);

????}?catch?(InterruptedException e) {

????????e.printStackTrace();

????}

}

(5).定制上锁失败策略

如果指定的customLockFailStrategy方法在本类外部,使用全限定名称

@Lock(name =?"foo-service",waitTime =?2,customLockFailStrategy =?"customLockTimeout")

public?String foo4(String foo, String bar) {

????try?{

????????TimeUnit.SECONDS.sleep(2);

????????log.info("acquire lock");

????}?catch?(InterruptedException e) {

????????e.printStackTrace();

????}

????return?"foo4";

}

private?String customLockTimeout(String foo, String bar) {

????return?"custom foo:"?+ foo +?" bar:"?+ bar;

}

文章来源:https://blog.csdn.net/qq_31457665/article/details/135766873
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。