Java基于Redis的分布式锁

分布式锁,其实最终还是要保证锁(数据)的一致性,说到数据一致性,基于ZK,ETCD数据一致性中间件做分数是锁,才是王道。但是Redis也能满足最基本的需求。

参考:

https://www.cnblogs.com/technologykai/p/8658689.html

https://www.cnblogs.com/rgcLOVEyaya/p/RGC_LOVE_YAYA_1003days.html

@Component
public class RedisLockManager implements Lock {
    Logger logger = LoggerFactory.getLogger(RedisLockManager.class);

    @Autowired
    RedisTool redisManager;
    /**
     * 请求锁的超时时间(ms)
     */
    private final long TIME_OUT = 30000;
    /**
     * 锁的有效时间(毫秒)
     */
    private long expire = 15000;
    private String key;
    private String value;

    private volatile boolean isLocked = false;

    public void setKey(String key) {
        this.key = key;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public void lock() {
        //系统当前时间,毫秒
        long nowTime = System.nanoTime();
        //请求锁超时时间,毫秒
        long timeout = TIME_OUT * 1000000;
        ThreadLocalRandom random = ThreadLocalRandom.current();
        try {
            while ((System.nanoTime() - nowTime) < timeout) {
                boolean flag = redisManager.tryGetDistributedLock(this.key, this.value, this.expire);
                if (flag) {
                    isLocked = true;
                    //上锁成功结束请求
                    break;
                }
                Thread.sleep(3, random.nextInt(500));
            }
        } catch (Exception e) {
            isLocked = false;
            logger.error(e.getMessage(), e);
        }
    }

    @Override
    public void unlock() {
        //释放锁
        //不管请求锁是否成功,只要已经上锁,客户端都会进行释放锁的操作
        if (isLocked) {
            redisManager.releaseDistributedLock(this.key, this.value);
            this.isLocked = false;
        }
    }

    @Override
    public void lockInterruptibly() {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean tryLock() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) {
        this.expire = unit.toMillis(time);
        this.lock();
        return this.isLocked;
    }

    @Override
    public Condition newCondition() {
        // TODO Auto-generated method stub
        return null;
    }
}

 

 


@Component
public class RedisTool {

  @Autwire
  Jedis jedis;
private final String LOCK_SUCCESS = "OK"; private final String SET_IF_NOT_EXIST = "NX"; private final String SET_WITH_EXPIRE_TIME = "PX"; /** * 尝试获取分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @param expireTime 超期时间 * @return 是否获取成功 */ public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) { String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } private final Long RELEASE_SUCCESS = 1L; /** * 释放分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @return 是否释放成功 */ public boolean releaseDistributedLock(String lockKey, String requestId) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); if (RELEASE_SUCCESS.equals(result)) { return true; } return false; } }

 

posted @ 2019-08-22 16:10  bookc  阅读(547)  评论(0编辑  收藏  举报