`

利用redis实现分布式锁(三) ——具体实现方式二

 
阅读更多

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁
 *
 * @Author guweiqiang
 */
public class DistributedLock {

    private static final Logger logger = LoggerFactory.getLogger(DistributedLock.class);

    private static final String LOCK_PREFIX = "SHP:LOCK:";

    private static final long DEFAULT_SLEEP_TIME = 100;
    /**
     * key值
     */
    private String lockKey;
    /**
     * value值,保证唯一
     */
    private String value = UUID.randomUUID().toString();
    /**
     * 有效期,单位:毫秒
     */
    private long expireTime;
    /**
     * 是否获得锁
     */
    private boolean locked = false;

    /**
     * 功能描述:构造函数
     *
     * @param shardedJedisClient shardedJedis客户端
     * @param lockKey            key值
     * @param expireTime         有效期,单位:毫秒
     * @Author gy
     * @Date 2016年8月14日下午6:10:49
     */
    public DistributedLock(String lockKey, long expireTime) {
        this.lockKey = LOCK_PREFIX + lockKey;
        this.expireTime = expireTime;
    }

    /**
     * 功能描述: 获取阻塞锁,如果锁空闲立即返回 ,获取失败 一直重试
     *
     * @param sleepTime 线程sleep时间,单位:毫秒
     * @throws InterruptedException
     * @Author gy
     * @Date 2016年8月14日下午9:12:40
     */
    public void lock(long paramSleepTime) throws InterruptedException {
        long sleepTime = paramSleepTime;
        logger.info("lock expireTime is {} ",expireTime);
        if (sleepTime <= 0) {
            sleepTime = DEFAULT_SLEEP_TIME;
        }
        do {
            boolean flag = setnxpx();
            if (flag) {
                locked = true;
                return;
            }
            Thread.sleep(sleepTime);
        } while (true);
    }

    /**
     * 功能描述: 获取立即返回锁,如果锁可用,立即返回true, 否则返回false
     *
     * @return 成功失败标志,true表示获取锁成功,false失败
     * @Author gy
     * @Date 2016年8月14日下午9:06:23
     */
    public boolean tryLock() {
        return tryLock(0, 0);
    }

    /**
     * 功能描述:获取等待重试锁,锁在给定的超时时间内空闲,则获取锁成功 返回true, 否则返回false
     *
     * @param timeout   重试超时时间,单位:毫秒
     * @param sleepTime 线程sleep时间,仅timeout大于0时有效,单位:毫秒
     * @return 成功失败标志,true表示获取锁成功,false失败
     * @Author gy
     * @Date 2016年8月14日下午9:01:13
     */
    public boolean tryLock(long timeout, long sleepTime) {
        long nano = System.nanoTime();
        try {
            do {
                boolean flag = setnxpx();
                if (flag) {
                    locked = true;
                    return true;
                }
                if (timeout <= 0 || sleepTime <= 0) {
                    return false;
                }
                Thread.sleep(sleepTime);
            } while ((System.nanoTime() - nano) < TimeUnit.MILLISECONDS.toNanos(timeout));
        } catch (Exception e) {
            logger.error("DistributedLock tryLock error:" + e.getMessage(), e);
        }
        return false;
    }

    /**
     * 功能描述: 释放锁
     *
     * @Author gy
     * @Date 2016年8月14日下午7:51:20
     */
    public void unLock() {
        release();
    }

    private boolean setnxpx() {
    	Long result = JedisUtil.setnx(lockKey, value);
        if (result==1) {
            return true;
        }
        return false;
    }

    private void release() {
        if (locked) {
        	// 获取redis中的值,验证是否与之前设置的值相等,如果相等,则删除,避免删除掉其他线程的锁
            String tmp = JedisUtil.get(lockKey);
            if (value.equals(tmp)) {
            	JedisUtil.del(lockKey);
            }
            locked = false;
        }
    }

}

 

 

使用方法:

        String key = "lockKey";
    	DistributedLock lock = new DistributedLock(key, 10000); // 超时10秒
    	if(!lock.tryLock()){ // 加锁失败,直接返回
    		responseBody.setResponseDto(0);
    		return responseBody;
    	}
  
         // 拿到锁之后,处理业务

 

 

JedisUtil工具类代码:

 

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.MultiKeyCommands;
import redis.clients.jedis.ShardedJedis;

import com.suning.framework.sedis.ShardedJedisAction;
import com.suning.framework.sedis.impl.ShardedJedisClientImpl;

/**
 * 功能描述: jedis 2.0 数据连接池类 〈功能详细描述〉
 * 
 */
public class JedisUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(JedisUtil.class);

    private static ShardedJedisClientImpl jedisClient;

    // 初始化此实例
    static {
        jedisClient = new ShardedJedisClientImpl("redis.conf");
    }

    private JedisUtil() {

    }

    /**
     * 从Redis的SET结构中取出一个值 并删除此值
     * 
     * @param key key
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String spop(final String key) {
        return jedisClient.execute(new ShardedJedisAction<String>() {
            @Override
            public String doAction(ShardedJedis shardedJedis) {
                return shardedJedis.spop(key);
            }
        });
    }

    /**
     * 从Redis的SET结构中取出多个值
     * 
     * @param key key
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Set<String> smembers(final String key) {
        return jedisClient.execute(new ShardedJedisAction<Set<String>>() {
            @Override
            public Set<String> doAction(ShardedJedis shardedJedis) {
                return shardedJedis.smembers(key);
            }
        });
    }

    /**
     * 从Redis的SET结构中删除多个成员
     * 
     * @param key key
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Long srem(final String key, final String[] members) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            @Override
            public Long doAction(ShardedJedis shardedJedis) {
                return shardedJedis.srem(key, members);
            }
        });
    }

    /**
     * 将一个member 元素加入到集合key 当中,已经存在于集合的member 元素将被忽略。 假如 key 不存在,则创建一个只包含member 元素作成员的集合。 当key 不是集合类型时,返回一个错误。时间复杂度O(1)
     * 
     * @param key
     * @param members
     * @return
     */
    public static Long sadd(final String key, final String member) {
        try {
            return jedisClient.execute(new ShardedJedisAction<Long>() {
                public Long doAction(ShardedJedis jedis) {
                    return jedis.sadd(key, member);
                }
            });
        } catch (Exception e) {
            LOGGER.error("SNEcsJedisUtil.sadd error = ", e);
            return null;
        }
    }

    /**
     * 从Redis的String添加多个成员
     * 
     * @param key key
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String set(final String key, final String value, final int expireTime) {
        try {
            return jedisClient.execute(new ShardedJedisAction<String>() {
                @Override
                public String doAction(ShardedJedis shardedJedis) {
                    String result = shardedJedis.set(key, value);
                    shardedJedis.expire(key, expireTime);
                    return result;
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.set error = ", e);
            return null;
        }
    }

    /**
     * 将序列化对象值value关联到key,如果key已经持有其他值,SET就覆写旧值,无视类型
     * 
     * @param key
     * @param value
     * @return
     */
    public static String set(final String key, final String value) {
        return jedisClient.execute(new ShardedJedisAction<String>() {
            public String doAction(ShardedJedis jedis) {
                return jedis.set(key, value);
            }
        });
    }

    /**
     * 返回key所关联的序列化对象。如果key不存在则返回null
     * 
     * @param key
     * @return
     */
    public static String get(final String key) {
        try {
            return jedisClient.execute(new ShardedJedisAction<String>() {
                public String doAction(ShardedJedis jedis) {
                    return jedis.get(key);
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.get error = ", e);
            return null;
        }
    }

    /**
     * 
     * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。key 不存在时,返回 null
     * 
     * @param key
     * @param value
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String getSet(final String key, final String value) {
        return jedisClient.execute(new ShardedJedisAction<String>() {
            public String doAction(ShardedJedis jedis) {
                return jedis.getSet(key, value);
            }
        });
    }

    /**
     * 〈一句话功能简述〉 〈功能详细描述〉
     * 
     * @param hash
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    public static String mset(final String... keysValues) {
        return jedisClient.execute(new ShardedJedisAction<String>() {
            public String doAction(ShardedJedis jedis) {
                if (jedis instanceof MultiKeyCommands) {
                    MultiKeyCommands shardedJedis = (MultiKeyCommands) jedis;
                    return shardedJedis.mset(keysValues);
                }
                return "";
            }
        });
    }

    /**
     * 批量返回一组Key所关联的序列化对象
     * 
     * @param keys
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    public static List<String> mget(final String... keys) {
        return jedisClient.execute(new ShardedJedisAction<List<String>>() {
            public List<String> doAction(ShardedJedis jedis) {
                if (jedis instanceof MultiKeyCommands) {
                    MultiKeyCommands shardedJedis = (MultiKeyCommands) jedis;
                    return shardedJedis.mget(keys);
                }
                return null;
            }
        });
    }

    /**
     * 移除给定的key。如果key不存在,则忽略该命令。
     * 
     * @param key
     * @return
     */
    public static Long del(final String key) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.del(key);
            }
        });
    }

    /**
     * 将哈希表key中的域field的值设为value。如果key不存在,一个新的哈希表被创建并 进行HSET操作。如果域field已经存在于哈希表中,旧值将被覆盖。
     * 
     * @param key field value
     * @return 如果field是哈希表中的一个新建域,并且值设置成功,返回1。如果哈希 表中域field已经存在且旧值已被新值覆盖,返回0。
     */
    public static Long hset(final String key, final String field, final String value) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.hset(key, field, value);
            }
        });
    }

    /**
     * 获取hash结构的元素个数。
     * 
     * @param key field value
     * @return
     */
    public static Long hlen(final String key) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.hlen(key);
            }
        });
    }

    /**
     * 返回哈希表 key 中给定域 field 的值。
     * 
     * @param key field
     * @return 给定域的值。 当给定域不存在或是给定key不存在时,返回null。
     */
    public static String hget(final String key, final String field) {
        return jedisClient.execute(new ShardedJedisAction<String>() {
            public String doAction(ShardedJedis jedis) {
                return jedis.hget(key, field);
            }
        });
    }
    
    /**
     * 
     * 功能描述: 获取指定权重之间的成员
     * 〈功能详细描述〉
     *
     * @param key 指定的有序集合
     * @param minScore 最小权重
     * @param maxScore 最大权重
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Set<String> zrangeByScore(final String key, final double minScore, final double maxScore) {
        return jedisClient.execute(new ShardedJedisAction<Set<String>>() {
            public Set<String> doAction(ShardedJedis jedis) {
                return jedis.zrangeByScore(key, minScore, maxScore);
            }
        });
    }

    /**
     * 同时将多个域-值对设置到哈希表key中。如果key不存在,一个空哈希表被创建并执行 HMSET操作。 时间复杂度O(N),N为域-值对的数量。
     * 
     * @param key hash
     * @return
     */
    public static String hmset(final String key, final Map<String, String> hash) {
        return jedisClient.execute(new ShardedJedisAction<String>() {
            public String doAction(ShardedJedis jedis) {
                return jedis.hmset(key, hash);
            }
        });
    }

    /**
     * 〈一句话功能简述〉 〈功能详细描述〉
     * 
     * @param key
     * @param fields
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本] (可选)
     */
    public static List<String> hmget(final String key, final String[] filedString) {
        return jedisClient.execute(new ShardedJedisAction<List<String>>() {
            public List<String> doAction(ShardedJedis jedis) {
                return jedis.hmget(key, filedString);
            }
        });
    }

    /**
     * 删除哈希表key中的指定域,不存在的域将被忽略。
     * 
     * @param key field
     * @return
     */
    public static Long hdel(final String key, final String... field) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.hdel(key, field);
            }
        });
    }

    public static Boolean hexists(final String key, final String field) {
        return jedisClient.execute(new ShardedJedisAction<Boolean>() {
            public Boolean doAction(ShardedJedis jedis) {
                return jedis.hexists(key, field);
            }
        });
    }

    public static Boolean exists(final String key) {
        return jedisClient.execute(new ShardedJedisAction<Boolean>() {
            public Boolean doAction(ShardedJedis jedis) {
                return jedis.exists(key);
            }
        });
    }

    public static Long rpush(final String key, final String member) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.rpush(key, member);
            }
        });
    }

    /**
     * 向list的头添加记录
     * 
     * @param key
     * @param member 被添加的值
     * @return
     */
    public static Long lpush(final String key, final String member) {
        try {
            return jedisClient.execute(new ShardedJedisAction<Long>() {
                public Long doAction(ShardedJedis jedis) {
                    return jedis.lpush(key, member);
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.lpush error = ", e);
            return null;
        }
    }

    /**
     * 保留list的start和end之间的数据,其他删除
     * 
     * @param key
     * @param start 起始位置
     * @param end 结束位置
     * @return
     */
    public static String ltrim(final String key, final long start, final long end) {
        try {
            return jedisClient.execute(new ShardedJedisAction<String>() {
                public String doAction(ShardedJedis jedis) {
                    return jedis.ltrim(key, start, end);
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.ltrim error = ", e);
            return null;
        }
    }

    /**
     * 删除count个指定value
     * 
     * @param key
     * @param count 个数
     * @param value 被删的值
     * @return
     */
    public static Long lrem(final String key, final long count, final String value) {
        try {
            return jedisClient.execute(new ShardedJedisAction<Long>() {
                public Long doAction(ShardedJedis jedis) {
                    return jedis.lrem(key, count, value);
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.lrem error = ", e);
            return null;
        }
    }

    /**
     * 查询list
     * 
     * @param key
     * @return
     */
    public static List<String> lrange(final String key) {
        try {
            return jedisClient.execute(new ShardedJedisAction<List<String>>() {
                public List<String> doAction(ShardedJedis jedis) {
                    return jedis.lrange(key, 0, -1);
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.lrange error = ", e);
        }
        return new ArrayList<String>();
    }

    public static Set<String> hkeys(final String key) {
        return jedisClient.execute(new ShardedJedisAction<Set<String>>() {
            public Set<String> doAction(ShardedJedis jedis) {
                return jedis.hkeys(key);
            }
        });
    }

    /**
     * 为哈希表 key 中的域 field 的值加上增量 increment 。 增量也可以为负数,相当于对给定域进行减法操作。 如果 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。 如果域 field
     * 不存在,那么在执行命令前,域的值被初始化为 0 。 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。 本操作的值被限制在 64 位(bit)有符号数字表示之内。
     * 
     * @param key
     * @param field
     * @param increment
     * @return 执行 hincrBy 命令之后,哈希表 key 中域 field 的值
     */
    public static Long hincrBy(final String key, final String field, final long increment) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.hincrBy(key, field, increment);
            }
        });
    }

    /**
     * 为给定key设置失效时刻,当key过期时,它会被自动删除 时间复杂度O(1)
     * 
     * @param key
     * @param unixTime Unix时间戳,单位为秒,使用时考虑误差
     * @return 1:成功;0:key不存在或不能为key设置失效时刻
     */
    public static Long expireAt(final String key, final long unixTime) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.expireAt(key, unixTime);
            }
        });
    }

    public static Long hsetnx(final String key, final String field, final String value) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.hsetnx(key, field, value);
            }
        });
    }

    public static Map<String, String> hgetAll(final String key) {
        return jedisClient.execute(new ShardedJedisAction<Map<String, String>>() {
            public Map<String, String> doAction(ShardedJedis jedis) {
                return jedis.hgetAll(key);
            }
        });
    }

    /**
     * 为给定key设置生存时间,当key过期时,它会被自动删除
     * 
     * @param key
     * @param seconds 秒
     * @return 1:成功;0:key不存在或不能为key设置生存时间时
     */
    public static Long expire(final String key, final int seconds) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.expire(key, seconds);
            }
        });
    }

    /**
     * @param arg0
     * @param arg1
     * @param arg2
     * @return
     * @see redis.clients.jedis.JedisCommands#setex(java.lang.String, int, java.lang.String)
     */
    public static String setex(final String key, final int field, final String value) {
        return jedisClient.execute(new ShardedJedisAction<String>() {
            public String doAction(ShardedJedis jedis) {
                return jedis.setex(key, field, value);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Long incr(final String arg0) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.incr(arg0);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Long decr(final String arg0) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.decr(arg0);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Set<String> zrevrange(final String key, final long start, final long end) {
        return jedisClient.execute(new ShardedJedisAction<Set<String>>() {
            public Set<String> doAction(ShardedJedis jedis) {
                return jedis.zrevrange(key, start, end);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Set<String> zrange(final String key, final long start, final long end) {
        return jedisClient.execute(new ShardedJedisAction<Set<String>>() {
            public Set<String> doAction(ShardedJedis jedis) {
                return jedis.zrange(key, start, end);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Double zscore(final String key, final String member) {
        return jedisClient.execute(new ShardedJedisAction<Double>() {
            public Double doAction(ShardedJedis jedis) {
                return jedis.zscore(key, member);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Long zcard(final String key) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.zcard(key);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Long zadd(final String key, final double score, final String member) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.zadd(key, score, member);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Long zremrangeByRank(final String key, final long start, final long end) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.zremrangeByRank(key, start, end);
            }
        });
    }

    /**
     * @param arg0
     * @return
     * @see redis.clients.jedis.JedisCommands#incr(java.lang.String)
     */
    public static Long zrem(final String key, final String... members) {
        return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.zrem(key, members);
            }
        });
    }

    /**
     * 功能描述: 随机获取集合中的元素<br>
     *
     * @param key
     * @param count
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static List<String> srandmember(final String key, final int count) {
        try {
            return jedisClient.execute(new ShardedJedisAction<List<String>>() {
                public List<String> doAction(ShardedJedis jedis) {
                    Jedis j = jedis.getShard(key);
                    return j.srandmember(key, count);
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.srandmember error = ", e);
            return null;
        }
    }
    
    /**
     * 从Redis的SET结构中删除成员
     * 
     * @param key key
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Long srem(final String key, final String members) {
        try {
            return jedisClient.execute(new ShardedJedisAction<Long>() {
                @Override
                public Long doAction(ShardedJedis shardedJedis) {
                    return shardedJedis.srem(key, members);
                }
            });
        } catch (Exception e) {
            LOGGER.error("JedisUtil.srem error = ", e);
            return null;
        }
    }
    
    /**
     * 将给定 key 的值设为 value ,如果key不存在时,返回1,否则返回失败
     * @param key
     * @param value
     * @return
     */
    public static Long setnx(final String key, final String value){
    	return jedisClient.execute(new ShardedJedisAction<Long>() {
            public Long doAction(ShardedJedis jedis) {
                return jedis.setnx(key, value);
            }
        });
    }
}

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics