【redis】分布式锁

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释放锁;如果大于锁设置的超时时间,则不需要再锁进行处理。

上面是新方案,区别不大


基于redis的分布式锁,欢迎大家批评

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component
public class DistributeLock {

    @Resource(name = "enableRedis")
    Redis redis;

    /**
     * 默认锁的超时时间,30s
     */
    static final int DEFAULT_KEY_TIMEOUT = 30;

    private void sleep() {
        try {
            Thread.sleep(200L);
        } catch (InterruptedException e) {
        }
    }

    /**
     * 会一直阻塞,直到加锁成功
     * 
     * @param key
     */
    public void lock(String key) {
        while (redis.setnx(key, "1") != 1) {
            sleep();
        }
        redis.expire(key, DEFAULT_KEY_TIMEOUT);
    }

    /**
     * 尝试加锁
     * 
     * @param key
     * @return 加锁失败返回false,or true
     */
    public boolean tryLock(String key) {
        boolean locked = redis.setnx(key, "1") == 1;
        if (locked) {
            redis.expire(key, DEFAULT_KEY_TIMEOUT);
        }
        return locked;
    }

    /**
     * 尝试加锁,会在一段时间内重复加锁,直到加锁成功 或 超时
     * 
     * @param key
     * @param millis
     *            尝试加锁时长,单位:秒
     * @return 加锁失败返回false,or true
     * @throws InterruptedException
     */
    public boolean tryLock(String key, long millis) throws InterruptedException {
        long deadline = System.currentTimeMillis() + millis;
        while (redis.setnx(key, "1") != 1) {
            sleep();
            millis = deadline - System.currentTimeMillis();
            if (millis <= 0L) {
                // 超时,加锁失败
                // 可以顺便检查该锁是不是没有设置超时时间
                if (redis.ttl(key) < 0) {
                    // 以防,该锁没有设置超时时间
                    redis.expire(key, DEFAULT_KEY_TIMEOUT);
                }
                return false;
            }
        }
        redis.expire(key, DEFAULT_KEY_TIMEOUT);
        return true;
    }

    public void unlock(String key) {
        redis.del(key);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值