redis 分布式 锁 java demo

2018-01-23

93

0

技术:redis + java8

运行环境:IDEA 15.2 + jdk8 + windows 7

demo功能:提供一个redis 分布式锁 demo

加锁

主要解决

1.获取锁超时 导致死锁

2.没有释放锁 导致死锁

/**
     * 加锁
     *
     * @param locaName       锁的key
     * @param acquireTimeout 获取超时时间
     * @param timeout        锁的超时时间
     * @return 锁标识
     */
    public String lockWithTimeout(String locaName, long acquireTimeout, long timeout) {
        Jedis client = null;
        String retIdentifier = null;
        try {
            client = jedisPool.getResource();
            String identifier = UUID.randomUUID().toString();
            String lockKey = "lock:" + locaName;
            // 超时时间,如果锁在这么多时间内还没有被使用者释放,则自动释放
            int lockExpire = (int) (timeout / 1000);

            // 获取锁的超时时间. 超过这个时间还没有获取到锁, 就放弃
            long end = System.currentTimeMillis() + acquireTimeout;
            while (System.currentTimeMillis() < end) {
                if (client.setnx(lockKey, identifier) == 1) {
                    client.expire(lockKey, lockExpire);
                    // 返回value值,用于释放锁时间确认
                    retIdentifier = identifier;
                    return retIdentifier;
                }
                // 返回-1代表key没有设置超时时间,为key设置一个超时时间
                if (client.ttl(lockKey) == -1) {
                    client.expire(lockKey, lockExpire);
                }

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        } catch (JedisException e) {
            e.printStackTrace();
        } finally {
            if (client != null) {
                client.close();
            }
        }
        return retIdentifier;
    }

释放锁

 public boolean releaseLock(String lockName, String identifier) {
        Jedis conn = null;
        String lockKey = "lock:" + lockName;
        boolean retFlag = false;
        try {
            conn = jedisPool.getResource();
            while (true) {
//如果事物被打断, 也没关系
                conn.watch(lockKey);
                // 通过前面返回的value值判断是不是该锁,若是该锁,则删除,释放锁
                if (identifier.equals(conn.get(lockKey))) {
                    Transaction transaction = conn.multi();
                    transaction.del(lockKey);
                    List<Object> results = transaction.exec();
                    if (results == null) {
                        continue;
                    }
                    retFlag = true;
                }
                conn.unwatch();
                break;
            }
        } catch (JedisException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return retFlag;
    }

测试结果

 

欢迎添加微信,互相学习↑↑↑ -_-

发表评论

全部评论:0条

白老虎

programming is not only to solve problems, ways to think