核心主要是利用Redis的senx和getset等命令进行操作,这些命令都是属于原子性的操作;
public synchronized boolean lockWithTimeout(String lockName, long acquireTimeout, long timeout) {
try {
// 获取连接
// 随机生成一个value
jedis = jedisPool.getResource();
String identifier = UUID.randomUUID().toString();
// 锁名,即key值
// 超时时间,上锁后超过此时间则自动释放锁
long lockTimeOut = System.currentTimeMillis()+timeout;
// 获取锁的超时时间,超过这个时间则放弃获取锁
long lockExpire = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis()<lockTimeOut) {
if (jedis.setnx(lockName, String.valueOf(lockExpire)) == 1) {
jedisLock=true;
return true;
}
String currentValue=jedis.get(lockName);
//当前值不为空,且当前值没有过期
if(currentValue!=null && Long.parseLong(currentValue)< System.currentTimeMillis()){
String oldValue=jedis.getSet(lockName,String.valueOf(lockExpire));
if(oldValue!=null && oldValue.equals(currentValue)){
jedisLock=true;
return true;
}
}
}
} catch (JedisException e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
return false;
}
/**
*
* @param lockName 锁的key
* @return
*/
public synchronized boolean releaseLock(String lockName) {
jedis = jedisPool.getResource();
try{
if(jedisLock){
jedis.del(lockName);
jedisLock=false;
}
}finally {
jedis.close();
}
return false;
}
根据Redis中的incr命令对产生自增;其中全局唯一ID的设计为
public void seckill() {
try {
if(lock.lockWithTimeout(lockName,1000,2000)) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
long id = Long.parseLong(format.format(calendar.getTime()))+jedis.incr("incrKey");
System.out.println("the lockKey is : " + id);
}
}finally {
lock.releaseLock(lockName);
}