分布式锁实现方案3、基于Redis的SET操作实现的分布式锁

2023-11-15

在我的上一篇文章中,关于redis分布式锁的写法,释放锁还有些缺陷,细节见评论部分,本文进一步做了完善。
分布式锁实现方案2、基于Redis的SET操作实现的分布式锁


package com.alioo.common.lock;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;

/**
 * <pre>
 * 基于Redis的SET操作实现的分布式锁
 * </pre>
 *
 * @author lzc.java@icloud.com
 */
@Slf4j
public class RedisDistributedLock {

    private JedisFacade redis;

    // 锁key
    private String lockKey;

    // 锁value
    private String lockVal;

    // 是否获得锁
    private boolean locked;

    private static final String RELEASE_LOCK_LUA_SCRIPT
        = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

    /**
     * @param redis
     * @param lockKey lockKey
     */
    public RedisDistributedLock(JedisFacade redis, String lockKey) {
        this.redis = redis;
        this.lockKey = lockKey;
    }

    /**
     * 阻塞式获取锁 ,不过有超时时间waitTime,超过了waitTime还未获取到锁将直接返回false
     *
     * @param lockTime 获得锁之后过期时间
     * @param waitTime 获得锁最多等待时间
     * @param unit
     * @return
     */
    protected boolean lock(long lockTime, long waitTime, TimeUnit unit) {
        try {
            // 超时控制 的时间可以从本地获取, 因为这个和锁超时没有关系, 只是一段时间区间的控制
            long start = System.currentTimeMillis();
            long milliTimeout = unit.toMillis(waitTime);

            while (System.currentTimeMillis() - start < milliTimeout) {

                boolean flag = tryLock(lockTime, unit);
                if (flag) {
                    return true;
                }

                Thread.sleep(10L);
            }
        } catch (InterruptedException e) {
            return false;
        }
        return false;
    }

    /**
     * 非阻塞,立即返回是否获取到锁
     *
     * @param lockTime 获得锁之后过期时间
     * @param unit
     * @return
     */
    public boolean tryLock(long lockTime, TimeUnit unit) {
        long milliLockTime = unit.toMillis(lockTime);

        //锁过期时间
        long lockExpireTime = System.currentTimeMillis() + milliLockTime;
        lockVal = String.valueOf(lockExpireTime);

        String ret = redis.set(lockKey, lockVal, "NX", "PX", milliLockTime);
        if ("OK".equals(ret)) {
            // 获取到锁, 设置相关标识
            locked = true;
            return true;
        }
        return false;
    }

    public boolean isLocked() {
        return locked;
    }

    /**
     * 释放锁
     */
    public void unlock() {
        if (!locked) {
            return;
        }

        // 当前线程加的锁也许已经过期自动释放了,然后又被其它线程加锁了,所以在释放锁的时候进一步根据lockVal再check下
        Object ret = redis.eval(RELEASE_LOCK_LUA_SCRIPT, Collections.singletonList(lockKey),
            Collections.singletonList(lockVal));
        log.info("释放锁lockKey:{},lockVal:{},ret:{}", lockKey, lockVal, ret);

    }

}

使用示例


        String lockKey = String.format("%s:%s:%s:%s", REDIS_LOCK_PREFIX, "biz_type", "sub_sub_type", userId);
        RedisDistributedLock lock = new RedisDistributedLock(jedisFacade, lockKey);
        Boolean result;
        try {
            boolean locked = lock.tryLock(5000, TimeUnit.MILLISECONDS);
            if (!locked) {
                throw new ServiceException(SysErrorCode.REDIS_LOCK_ERROR);
            }
            
            // do your service
			doYourService()

        } finally {
            lock.unlock();
        }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分布式锁实现方案3、基于Redis的SET操作实现的分布式锁 的相关文章

随机推荐

  • java上机题编程题

    1 编写程序 用数组实现乘法小九九的存储和输出 提示 采用多个一维数组 public class Multipation public static void main String args TODO Auto generated met
  • Linux一句话精彩问答--

    0001 修改主机名 陈绪 vi etc sysconfig network 修改HOSTNAME一行为 HOSTNAME 主机名 没有这行 那就添加这一行 吧 然后运行命令 hostname 主机名 一般还要修改 etc hosts文件中
  • 【javascript】作用域的理解(LHS,RHS查询)

    作用域是什么 一 理解作用域 任何javascript代码片段在执行前都要进行编译 先看一个例子吧 先思考一下这行代码是如何被编译的 var a 33 估计大部分人看到这行代码 会说首先声明一个变量a 然后给它赋值33 但实际上并没有这么简
  • Linux系统与管理 - (三)Linux常用命令解析

    自说 学习路径 目录和文件 查找目录和文件 查看文件 压缩及解压 自说 操作Linux系统必不可少的常用命令 坚持学习吧 每天一点点 总归是有收获的 学习路径 Linux系统与管理 一 安装Linux系统 Linux系统与管理 二 Linu
  • pyautogui 使用示例

    文章目录 coding utf 8 import pyautogui import time def test distance 1000 time sleep 5 pyautogui moveTo 400 300 while distan
  • js做简易信息聊天

    div div div img src img img1 jpg div
  • 常用Pytorch中张量(Tensor)的创建

    from IPython core interactiveshell import InteractiveShell InteractiveShell ast node interactivity all import torch a to
  • 华为手机连电脑当摄像头用_DxOMark评六大最佳手机摄像头:华为P40 Pro独揽四个第一...

    来源 快科技 DxOMark今天发布了一份特殊的榜单 按照照片 视频 广角 夜间摄影 变焦 散景 背景虚化 六大类 评选出了每个分类表现最好的手机 结果华为P40 Pro四次上榜 另外两个则被三星拿下 最佳照片 华为P40 Pro 拍照成绩
  • 【CLIP详读】

    个人网站 https tianfeng space 一 前言 OpenAI的CLIP项目自从推出以来 CLIP引起了广泛的关注 它的方法看似简单 但效果非常出色 许多结果令人惊叹 例如 预训练模型可以在任何视觉分类数据集上实现出色的效果 而
  • ubuntu apt-get dpkg应用中的一些问题及解决方法

    一 在用sudo apt get install 安装软件时 由于速度太慢 想换个软件源 直接关闭了终端 apt get但进程没有结束 结果终端提示 E 无法获得锁 var lib dpkg lock open 11 资源暂时不可用 E 无
  • 【Javadoc生成开发文档(Terminal或IDEA中)】

    Javadoc生成开发文档 一 Javadoc工具介绍 二 常用标记 三 使用方式 四 生成文档的两种方式 1 Terminal方式 2 IDE方式 一 Javadoc工具介绍 大家在查看官网文档的时候 会不会感慨人家的帮助文档写的真有逻辑
  • 轻松刷脸是美妙的线下消费体验过程

    刷脸支付的过程非常的简单 你不需要带钱包 信用卡或手机 支付时只需要自己面对刷脸支付pos机屏幕上的摄像头 刷脸支付系统会自动将消费者面部信息与个人账户相关联 整个交易过程十分便捷 在移动支付的快速发展中 消费者逐渐习惯使用移动支付 即使身
  • 交换机的Access口与Trunk口

    基本概念 Access类型的端口只能属于1个VLAN 一般用于连接计算机的端口 Trunk类型的端口可以允许多个VLAN通过 可以接收和发送多个VLAN的报文 一般用于交换机之间连接的端口 处理流程 Acess端口收报文 收到一个报文 判断
  • Python 分割技术提取图像和视频中对象

    计算机视觉是计算机查看和识别对象的媒介 计算机视觉的目标是使计算机能够分析图像和视频中的对象 解决不同的视觉问题 对象分割为方便分析图像和视频中的对象铺平了道路 对不同领域做出了巨大贡献 例如医学 自动驾驶汽车的视觉以及图像和视频的背景编辑
  • vue form 滑动验证码、手机短信验证

    话不多说直接上效果图 vue 注册首页 校验 滑动验证 页面源码
  • mysql explain执行计划

    mysql explain执行计划 mysql gt EXPLAIN SELECT FROM t item i LEFT JOIN t sku s ON i item id s item id LEFT JOIN t sku stock t
  • 楠姐技术漫话:接着唠唠社区发现

    halo 大家好 很开心又和大家见面了 在第一篇技术漫话 图计算的那些事 发布之后 楠姐收到了很多鼓励和支持 非常感谢大家的喜欢 所以楠姐尽自己所能马不停蹄开始第二篇的创作 虽迟但到 也尝试在第二期中 在可读性和观感上尽量做些优化和进步 本
  • Managing Big Data with MySQL学习笔记

    Managing Big Data with MySQL学习笔记 Intro Week 1 How Relational Databases Help Solve Those Problems Database Design Tools E
  • Vue 高德地图实现添加标记,AMap.PlaceSearch 地点搜索,根据页面主题修改地图样式

    Vue 高德地图实现添加标记 AMap PlaceSearch 地点搜索 根据页面主题修改地图样式 效果图 成为开发者并创建key 详细请查阅官方文档 https developer amap com api jsapi v2 guide
  • 分布式锁实现方案3、基于Redis的SET操作实现的分布式锁

    在我的上一篇文章中 关于redis分布式锁的写法 释放锁还有些缺陷 细节见评论部分 本文进一步做了完善 分布式锁实现方案2 基于Redis的SET操作实现的分布式锁 package com alioo common lock import