支持 redis 2.6.12以上版本。
同时也是redis官网推荐的一种实现方式,可以到http://redis.io/commands/set 看官网说法
package com.extracme.evcard.redis; import java.util.UUID; import redis.clients.jedis.Jedis; /** * * redis做分布式锁的实现 * * @author wu yibo */ public class JedisLock { private static final int ONE_SECOND = 1000; public static final int DEFAULT_EXPIRY_TIME_MILLIS = 5 * ONE_SECOND; private final Jedis jedis; private final String lockKey; private final int lockExpiryInMillis; private final UUID lockUUID; private boolean isLocked = false; /** * 生成锁对象 * @param jedis * @param lockKey */ public JedisLock(Jedis jedis, String lockKey) { this(jedis, lockKey, DEFAULT_EXPIRY_TIME_MILLIS); } /** * 生成锁对象 * @param jedis * @param lockKey * @param expiryTimeMillis */ public JedisLock(Jedis jedis, String lockKey, int expiryTimeMillis) { this(jedis, lockKey, expiryTimeMillis, UUID.randomUUID()); } /** * 生成锁对象 * @param jedis * @param lockKey * @param expiryTimeMillis * @param uuid */ public JedisLock(Jedis jedis, String lockKey, int expiryTimeMillis, UUID uuid) { this.jedis = jedis; this.lockKey = lockKey; this.lockExpiryInMillis = expiryTimeMillis; this.lockUUID = uuid;; } public UUID getLockUUID() { return lockUUID; } public String getLockKey() { return lockKey; } /** * 加锁 * @return * * @author wu yibo */ public synchronized boolean acquire() { return acquire(jedis); } /** * 加锁. * 这里是用的是redis 的set指令来实现加锁,详情请看:http://redis.io/commands/set * @param jedis * @return * * @author wu yibo */ protected synchronized boolean acquire(Jedis jedis) { //nx表示:Only set the key if it does not already exist. //ps表示:Set the specified expire time, in milliseconds。超时时间的单位是毫秒 if(!isLocked) { isLocked = jedis.set(this.lockKey, this.lockUUID.toString(), "nx", "px", this.lockExpiryInMillis) != null; return isLocked; } return false; } /** * 释放锁 * * @author wu yibo */ public synchronized void release() { release(jedis); } /** * 释放锁 * @param jedis * * @author wu yibo */ protected synchronized void release(Jedis jedis) { if(this.isLocked) { //使用eval指令执行 Lua 脚本 //如果redis中该key对应的值已经变掉了,不再执行删除指令。防止偶然情况下线程执行时间过长,导致释放锁的时候把其他线程的锁释放掉 jedis.eval("if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end", 1, this.lockKey, this.lockUUID.toString()); } isLocked = false; } /** * 检查是否已经加锁 * @return * * @author wu yibo */ public synchronized boolean isLocked() { return this.isLocked; } }