- Notifications
You must be signed in to change notification settings - Fork0
The distributed lock tool for java.(java 实现开箱即用基于 redis 的分布式锁,支持可重入锁获取。内置整合 spring、springboot。)
License
houbb/lock
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
lock 为 java 设计的渐进式分布式锁,开箱即用,纵享丝滑。
开源地址:https://github.com/houbb/lock
开箱即用,支持注解式和过程式调用
支持可重入锁获取
基于 mysql 的分布式锁
基于 redis 的分布式锁
内置支持多种 redis 的整合方式
渐进式设计,可独立于 spring 使用
整合 spring
整合 spring-boot
jdk1.7+
maven 3.x+
<dependency> <groupId>com.github.houbb</groupId> <artifactId>lock-core</artifactId> <version>1.7.2</version></dependency>
基于本地 MAP 的入门测试案例。
ILocklock =LockBs.newInstance();Stringkey ="ddd";try {// 加锁booleanlockFlag =lock.tryLock(key);Assert.assertTrue(lockFlag);}catch (Exceptione) {thrownewRuntimeException(e);}finally {// 释放锁lock.unlock(key);}
| 方法签名 | 参数说明 | 返回值说明 | 版本标记 |
|---|---|---|---|
boolean tryLock(final ILockContext context) | context: 锁操作上下文对象 | 加锁成功返回 true,失败 false | since 1.5.0 |
boolean tryLock(String key, TimeUnit timeUnit, long lockTime, long waitLockTime, boolean reentrant) | key: 锁标识timeUnit: 时间单位lockTime: 锁持有时长waitLockTime: 最大等待时长reentrant: 是否允许重入 | 加锁成功返回 true,失败 false | since 1.5.0 |
boolean tryLock(String key, TimeUnit timeUnit, long lockTime, long waitLockTime) | key: 锁标识timeUnit: 时间单位lockTime: 锁持有时长waitLockTime: 最大等待时长(默认 reentrant=true) | 加锁成功返回 true,失败 false | since 0.0.1 |
boolean tryLock(String key, TimeUnit timeUnit, long lockTime) | key: 锁标识timeUnit: 时间单位lockTime: 锁持有时长(默认 waitLockTime=0 仅尝试一次) | 加锁成功返回 true,失败 false | since 0.0.1 |
boolean tryLock(String key, long lockTime) | key: 锁标识lockTime: 锁持有时长(秒)(默认 timeUnit=SECONDS) | 加锁成功返回 true,失败 false | since 0.0.1 |
boolean tryLock(String key) | key: 锁标识(默认 lockTime=10秒) | 加锁成功返回 true,失败 false | since 0.0.1 |
boolean unlock(String key) | key: 锁标识注意: 释放锁不重试,所有 key 有过期时间 | 释放成功返回 true,失败 false | since 0.0.1 |
提供了较多方法,只是为了使用更加便捷。
boolean tryLock(final ILockContext context); 中的入参,和参数一一对应,默认值也相同。
context 的引入,为了避免后续的配置项较多,方法会膨胀的问题。
ILockContextlockContext =LockContext.newInstance() .key(key) .lockTime(LockConst.DEFAULT_LOCK_TIME) .waitLockTime(LockConst.DEFAULT_WAIT_LOCK_TIME) .reentrant(LockConst.DEFAULT_REENTRANT) .timeUnit(LockConst.DEFAULT_TIME_UNIT);booleanlockFlag =lock.tryLock(lockContext);
概念:可重入性(reentrancy)是指一个线程在拥有一个资源(通常是一个锁)的情况下,再次获取该资源时不会造成死锁。可重入性在多线程编程中非常重要,因为它可以避免因线程之间的相互依赖而导致的死锁。
我们支持一个线程可以多次获取一个锁,默认是可重入的。
@TestpublicvoidreTest() {ILocklock =LockBs.newInstance();Stringkey ="ddd";try {// 加锁booleanlockFlag =lock.tryLock(key);//1. 首次获取锁成功Assert.assertTrue(lockFlag);//2. 重新获取锁成功booleanreLockFlag =lock.tryLock(key);Assert.assertTrue(reLockFlag); }catch (Exceptione) {thrownewRuntimeException(e); }finally {// 释放锁lock.unlock(key); }}
当然,我们也支持不可重入的形式,指定对应的配置即可。
publicvoidnoReTest() {ILocklock =LockBs.newInstance();Stringkey ="ddd";try {ILockContextlockContext =LockContext.newInstance() .key(key) .waitLockTime(5) .reentrant(false);// 指定不可重入booleanlockFlag =lock.tryLock(lockContext);//1. 首次获取锁成功Assert.assertTrue(lockFlag);//2. 不是重入,第二次获取失败booleanreLockFlag =lock.tryLock(lockContext);Assert.assertFalse(reLockFlag); }catch (Exceptione) {thrownewRuntimeException(e); }finally {// 释放锁lock.unlock(key); }}
不可重入锁,第二次获取就会失败。
为了便于拓展,LockBs 的配置支持自定义:
LockBs.newInstance() .id(Ids.uuid32())//id 生成策略 .cache(JedisRedisServiceFactory.pooled("127.0.0.1",6379))//缓存策略 .lockSupport(newRedisLockSupport())// 锁实现策略 .lockKeyFormat(newLockKeyFormat())// 针对 key 的格式化处理策略 .lockReleaseFailHandler(newLockReleaseFailHandler())//释放锁失败处理 ;
可配置项如下:
| 属性名 | 类型 | 默认值 | 说明 | 版本标记 |
|---|---|---|---|---|
| id | Id | Ids.uuid32() | 唯一标识生成策略 | since 0.0.4 |
| cache | ICommonCacheService | new CommonCacheServiceMap() | 缓存实现策略 | since 0.0.4 |
| lockSupport | ILockSupport | new CommonCacheLockSupport() | 锁底层支持策略 | since 1.0.0 |
| lockKeyFormat | ILockKeyFormat | new LockKeyFormat() | 锁 Key 格式化处理器 | since 1.2.0 |
| lockReleaseFailHandler | ILockReleaseFailHandler | new LockReleaseFailHandler() | 锁释放失败处理策略 | since 1.2.0 |
| tryLockIntervalMills | int | LockConst.DEFAULT_TRY_LOCK_INTERVAL_MILLS | 尝试加锁的轮询间隔(毫秒) | since 1.6.0 |
<dependency> <groupId>com.github.houbb</groupId> <artifactId>lock-spring</artifactId> <version>1.7.2</version></dependency>
@EnableLock 启用分布式锁。
@EnableRedisConfig 启用 redis 的默认配置。
@Configurable@ComponentScan(basePackages = "com.github.houbb.lock.test.service")@EnableLock@EnableRedisConfigpublic class SpringConfig {}EnableLock 注解说明,和引导类对应:
| 属性名 | 描述 | 默认值 |
|---|---|---|
| id() | 唯一标识生成策略 | "lockId" |
| cache() | 缓存实现策略的 Bean 名称 | "springRedisService" |
| lockKeyFormat() | 加锁 Key 格式化策略 | "lockKeyFormat" |
| lockKeyNamespace() | 锁 Key 的默认命名空间 | LockConst.DEFAULT_LOCK_KEY_NAMESPACE |
| lockReleaseFailHandler() | 锁释放失败处理类 | "lockReleaseFailHandler" |
其中springRedisService 使用的是redis-config 中的实现。
对应注解@EnableRedisConfig,redis 的配置信息如下:
| 配置 | 说明 | 默认值 |
|---|---|---|
| redis.address | redis 地址 | 127.0.0.1 |
| redis.port | redis 端口 | 6379 |
| redis.password | redis 密码 |
当然,你可以使用自己想用的其他缓存实现,只需要实现对应的接口标准即可。
我们可以直接LockBs 的引导类,这种适合一些更加灵活的场景。
@ContextConfiguration(classes =SpringConfig.class)@RunWith(SpringJUnit4ClassRunner.class)publicclassSpringServiceRawTest {@AutowiredprivateUserServiceuserService;@AutowiredprivateLockBslockBs;@TestpublicvoidqueryLogTest() {finalStringkey ="name";try {booleanlockFlag =lockBs.tryLock(key);finalStringvalue =userService.rawUserName(1L); }catch (Exceptionexception) {thrownewRuntimeException(exception); }finally {lockBs.unlock(key); } }}
当然,我们可以在方法上直接指定注解@Lock,使用更加方便。
直接使用,AOP 切面生效即可。
@ServicepublicclassUserService {@LockpublicStringqueryUserName(LonguserId) { }@Lock(value ="#user.name")publicvoidqueryUserName2(Useruser) { }}
@Lock 属性说明,value 用于指定 key,支持 SPEL 表达式。
如果 aop 中拦截获取锁失败,默认会抛出异常。
其他属性,和引导类的方法参数一一对应。
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| value() | String | "" | 锁的 Key 策略(支持 SpEL 表达式) 例: @Lock("order:#{#orderId}") |
| timeUnit() | TimeUnit | TimeUnit.SECONDS | 时间单位(秒/毫秒等) |
| waitLockTime() | long | LockConst.DEFAULT_WAIT_LOCK_TIME | 等待锁的最长时间 通常为 0(仅尝试一次)或正数(持续重试) |
| lockTime() | long | LockConst.DEFAULT_LOCK_TIME | 锁持有时间 通常为 10-30 秒(防止死锁) |
| reentrant() | boolean | LockConst.DEFAULT_REENTRANT | 是否允许重入 通常为 true(同一线程可重复获取) |
<dependency> <groupId>com.github.houbb</groupId> <artifactId>lock-springboot-starter</artifactId> <version>1.7.2</version></dependency>
所有的配置会自动生效。
使用方式同 spring。
- 支持锁的可重入
持有锁的线程可以多次获取锁
分布式锁注解支持
spring 的锁支持拓展性扩展,而不是局限于 redis-lock
watch-dog,添加锁的自动续租?
下面是一些缓存系列的开源矩阵规划。
| 名称 | 介绍 | 状态 |
|---|---|---|
| resubmit | 防止重复提交核心库 | 已开源 |
| rate-limit | 限流核心库 | 已开源 |
| cache | 手写渐进式 redis | 已开源 |
| lock | 开箱即用的分布式锁 | 已开源 |
| common-cache | 通用缓存标准定义 | 已开源 |
| redis-config | 兼容各种常见的 redis 配置模式 | 已开源 |
| quota-server | 限额限次核心服务 | 待开始 |
| quota-admin | 限额限次控台 | 待开始 |
| flow-control-server | 流控核心服务 | 待开始 |
| flow-control-admin | 流控控台 | 待开始 |
About
The distributed lock tool for java.(java 实现开箱即用基于 redis 的分布式锁,支持可重入锁获取。内置整合 spring、springboot。)
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.