战狂粗人张

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  228 随笔 :: 0 文章 :: 12 评论 :: 20万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

一、Redis命令

 1、setnx()命令:

setnx的含义就是SET if Not Exists,其主要有两个参数 setnx(key, value)。

该方法是原子的,如果key不存在,则设置当前key成功,返回1;如果当前key已经存在,则设置当前key失败,返回0。

2、get()命令:

get(key) 获取key的值,如果存在,则返回;如果不存在,则返回nil;

3、getset()命令:

这个命令主要有两个参数 getset(key, newValue)。该方法是原子的,对key设置newValue这个值,并且返回key原来的旧值。

假设key原来是不存在的,那么多次执行这个命令,会出现下边的效果:

(1)getset(key, "value1")  返回nil   此时key的值会被设置为value1;

(2)getset(key, "value2")  返回value1   此时key的值会被设置为value2;

(3)依次类推!

 

二、具体的使用步骤如下:

1、setnx(lockkey, 当前时间+过期超时时间) ,如果返回1,则获取锁成功;如果返回0则没有获取到锁,转向2。

2、get(lockkey)获取值oldExpireTime ,并将这个value值与当前的系统时间进行比较,如果小于当前系统时间,则认为这个锁已经超时,可以允许别的请求重新获取,转向3。

3、计算newExpireTime=当前时间+过期超时时间,然后getset(lockkey, newExpireTime) 会返回当前lockkey的值currentExpireTime。

4、判断currentExpireTime与oldExpireTime 是否相等,如果相等,说明当前getset设置成功,获取到了锁。如果不相等,说明这个锁又被别的请求获取走了,那么当前请求可以直接返回失败,或者继续重试。

5、在获取到锁之后,当前线程可以开始自己的业务处理,当处理完毕后,比较自己的处理时间和对于锁设置的超时时间,如果小于锁设置的超时时间,则直接执行delete释放锁;如果大于锁设置的超时时间,则不需要再锁进行处理。

三、实例代码

1、实现分布式锁DistributedLockHandler类:

复制代码
package tk.mybatis.springboot.distributedLock;
 
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
 
@Service("distributedLockHandler")
public class DistributedLockHandler {
 
    private static final Integer Lock_Timeout = 3;
 
    private Jedis jedis;
 
    /**
     * 外部调用加锁的方法
     * @param lockKey 锁的名字
     * @param timeout 超时时间(放置时间长度,如:5L)
     * @return
     */
    public boolean tryLock(String lockKey, Long timeout) {
        try {
            Long currentTime = System.currentTimeMillis();//开始加锁的时间
            boolean result = false;
            
            while (true) {
                if ((System.currentTimeMillis() - currentTime) / 1000 > timeout) {//当前时间超过了设定的超时时间
                    System.out.println("Execute DistributedLockHandler.tryLock method, Time out.");
                    break;
                } else {
                    result = innerTryLock(lockKey);
                    if (result) {
                        break;
                    } else {
                        System.out.println("Try to get the Lock,and wait 100 millisecond....");
                        Thread.sleep(100);
                    }
                }
            }
            return result;
        } catch (Exception e) {
            System.out.println("Failed to run DistributedLockHandler.getLock method."+ e);
            return false;
        }
    }
    
    /**
     * 释放锁
     * @param lockKey 锁的名字
     */
    public void realseLock(String lockKey) {
        if(!checkIfLockTimeout(System.currentTimeMillis(), lockKey)){
            jedis.del(lockKey);
        }
    }
    
    /**
     * 内部获取锁的实现方法
     * @param lockKey 锁的名字
     * @return
     */
    private boolean innerTryLock(String lockKey) {
        
        long currentTime = System.currentTimeMillis();//当前时间
        String lockTimeDuration = String.valueOf(currentTime + Lock_Timeout + 1);//锁的持续时间
        Long result = jedis.setnx(lockKey, lockTimeDuration);
        
        if (result == 1) {
            return true;
        } else {
            if (checkIfLockTimeout(currentTime, lockKey)) {
                String preLockTimeDuration = jedis.getSet(lockKey, lockTimeDuration);
                if (currentTime > Long.valueOf(preLockTimeDuration)) {
                    return true;
                }
            }
            return false;
        }
        
    }
 
    /**
     * 判断加锁是否超时
     * @param currentTime 当前时间
     * @param lockKey 锁的名字
     * @return
     */
    private boolean checkIfLockTimeout(Long currentTime, String lockKey) {
        if (currentTime > Long.valueOf(jedis.get(lockKey))) {//当前时间超过锁的持续时间
            return true;
        } else {
            return false;
        }
    }
 
    public DistributedLockHandler setJedis(Jedis jedis) {
        this.jedis = jedis;
        return this;
    }
 
}
复制代码

 

2、调用Demo类:

复制代码
package tk.mybatis.springboot.distributedLock;
 
import redis.clients.jedis.Jedis;
 
/**
 * 基于redis的setnx()、get()、getset()方法 分布式锁
 * @author KF01
 *
 */
public class Demo {
private static final String lockKey = "Lock.TecentIm_Interface_Counter"; public static void main(String[] args) { Jedis jedis = new Jedis("127.0.0.1", 6379); DistributedLockHandler distributedLockHandler = new DistributedLockHandler().setJedis(jedis); try{ boolean getLock = distributedLockHandler.tryLock(lockKey, Long.valueOf(5)); if(getLock){ // Do your job System.out.println("Do your job........"); } }catch(Exception e){ System.out.println(e); }finally { distributedLockHandler.realseLock(lockKey); } } }
复制代码

 

posted on   战狂粗人张  阅读(1001)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
历史上的今天:
2020-05-12 关于Condition
2020-05-12 关于并发的相关概念
2020-05-12 关于wait/notify(二)
2020-05-12 关于wait/notify(一)
2020-05-12 关于Volatile(一)
2020-05-12 关于Volatile(二)
点击右上角即可分享
微信分享提示