1 Star 1 Fork 1

xiami/handy-lock

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

简介

handy-lock是一个简易的redis分布式锁实现类库。它并不像redission实现的分布式锁那样严谨,但是简单易用,而且可以用于codis。

主要特性

  • 兼容codis
  • setnx原子加锁,lua脚本原子释放锁
  • 每次加锁value用guid,不会存在释放别人的锁的问题
  • 加锁和释放锁自带重试机制
  • 提供了自动延期的锁,避免过期时间长度选择的困境

引用

<dependency>
    <groupId>com.github.free-jungle</groupId>
    <artifactId>handy-lock-starter</artifactId>
    <version>1.0.0</version>
</dependency>

配置

redis操作使用springboot的RedisTemplate实现,所以配置和spring.redis配置是一样的

spring:
  redis:
    host: 127.0.0.1
    port: 6379

使用举例

例1: 使用RedisLockManager加锁[推荐]


@Resource
private RedisLockManager redisLockManager;

public void lockUseLockManager(String id) {
    String lockKey = String.format("%s.%s#%s", this.getClass().getCanonicalName(), "lockUseLockManager", id);
    try (RedisLock redisLock = redisLockManager.fetchAndTryLock(lockKey, 5000, 1000, 2)) {
        TimeUnit.SECONDS.sleep(2L);
    } catch (LockFailException | IOException | InterruptedException ex) {
        LOGGER.error("error when lockUseLockManager", ex);
    }
}

例2: 注解方式加锁-静态key

@RedisDistributedLockable(key = "com.github.free.jungle.lock.examples.service.impl.lockUseAnnotation",
        expireInMilliseconds = 10000, waitInMilliseconds = 10, tryCount = 1)
public void lockUseAnnotation() {
    LOGGER.info("start lockUseAnnotation");
    try {
        TimeUnit.MILLISECONDS.sleep(100L);
    } catch (Exception ex) {
        LOGGER.error("error when lockUseAnnotation", ex);
    }
    LOGGER.info("end lockUseAnnotation");
}

虽然提供了注解的使用方式,还是推荐直接用例1的方式,代码易读,易懂,用起来也很简单,没有比 注解麻烦。

例3: 注解方式加锁-动态key

@RedisDistributedLockable(keySpel = "'com.github.free.jungle.lock.examples.service.impl.lockUserAnnotationWithSpel#'+#id",
            expireInMilliseconds = 10000, waitInMilliseconds = 1000, tryCount = 3)
public void lockUserAnnotationWithSpel(String id) {
    LOGGER.info("start lockUserAnnotationWithSpel:{}", id);
    try {
        TimeUnit.SECONDS.sleep(2L);
    } catch (Exception ex) {
        LOGGER.error("error when lockUseAnnotation", ex);
    }
    LOGGER.info("end lockUserAnnotationWithSpel:{}", id);
}

适用于key需要根据入参动态拼装的情况,其中keySpel是spel表达式

例4: 自动延长过期时间的分布式锁[推荐]

上面的用法有一个困难的问题,就是过期时间参数(expireInMilliseconds)的配置可能很难,因为:

  • 锁有效时间太短,任务还没执行完,redis就过期了,这样分布式执行就会产生并发的问题
  • 锁有效期太长,极端情况当程序异常退出,没有正确释放锁,锁长时间无法获取,导致任务无法进行的问题

所以实现了一个能够自动延长锁有效时间的加锁方法,使用方法如下:

@Resource
private RedisLockManager redisLockManager;

public void lockWithScheduleUseLockManager(String id) {
    String lockKey = String.format("%s.%s#%s", this.getClass().getCanonicalName(), "lockUseLockManager", id);
    try (RedisLock redisLock = redisLockManager.fetchAndTryLockWithSchedule(lockKey)) {
        TimeUnit.SECONDS.sleep(30L);
    } catch (LockFailException | IOException | InterruptedException ex) {
        LOGGER.error("error when lockUseLockManager", ex);
    }
}

详细方法说明

RedisLockManager 的方法有较为详尽的注释,请直接查看源码。

样例项目

handy-lock-examples是专门的使用样例项目,作为参考使用

已知问题

只是实现了客户端层面的简易分布式锁,所以无法处理由于redis服务端故障造成数据不一致的问题,需要 更严谨的分布式锁的情况建议用Redssion

希望对你有所帮助

MIT License Copyright (c) 2019-present kechangqing. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

简易的redis分布式锁实现 展开 收起
Java
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/tim_guai/handy-lock.git
git@gitee.com:tim_guai/handy-lock.git
tim_guai
handy-lock
handy-lock
master

搜索帮助

Cb406eda 1850385 E526c682 1850385