redis分布式锁
文章参考 https://www.cnblogs.com/linjiqin/p/8003838.html#!comments
1.获取锁
采用这种方式的宗旨就是加锁和设置过期必须在一起 原子性
使用jedis这个方法public String set(final String key, final String value, final String nxxx, final String expx,final long time)
private static final String SET_IF_NOT_EXIST = "NX";//nxxx
private static final String SET_WITH_EXPIRE_TIME = "PX";expx
public static boolean incWorkOrderTryLock(String incidentCode, String requestId) {
boolean flag = false;
try {
RedisService redisService = SpringContextUtil.getBean(RedisService.class);
String str = redisService.setNx(BmConstant.INCWORKORDER_LOCK_PREFIX + incidentCode, requestId, BmConstant.INCWORKORDER_LOCK_EXPIRE_TIME);
if("OK".equals(str)){
flag = true;
}
} catch (Exception e) {
log.error("tryIncWorkOrderLock failed",e);
}
return flag;
}
2.阻塞方式获取锁
采用这种方式的宗旨就是加锁和设置过期必须在一起 原子性
public static boolean incWorkOrderBlockLock(String incidentCode, String requestId, long blockTime){
boolean flag = false;
try {
RedisService redisService = SpringContextUtil.getBean(RedisService.class);
while (blockTime >= 0){
String str = redisService.setNx(BmConstant.INCWORKORDER_LOCK_PREFIX + incidentCode, requestId, BmConstant.INCWORKORDER_LOCK_EXPIRE_TIME);
if ("OK".equals(str)){
flag = true;
break;
}
Thread.sleep(BmConstant.INCWORKORDER_LOCK_SLEEP_TIME) ;
blockTime -= BmConstant.INCWORKORDER_LOCK_SLEEP_TIME ;
}
} catch (Exception e) {
log.error("blockIncWorkOrderLock failed",e);
}
return flag ;
}
3.释放锁
采用这种方式的宗旨就是 原子性
public static boolean incWorkOrderUnLock(String incidentCode, String requestId){
boolean flag = false;
try {
RedisService redisService = SpringContextUtil.getBean(RedisService.class);
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = redisService.eval(script, Collections.singletonList(BmConstant.INCWORKORDER_LOCK_PREFIX + incidentCode),
Collections.singletonList(requestId));
if (1l == (long)result){
flag = true;
}
} catch (Exception e) {
log.error("unIncWorkOrderLock failed",e);
}
return flag;
}
错误示例
public static void wrongReleaseLock2(Jedis jedis, String lockKey, String requestId) {
// 判断加锁与解锁是不是同一个客户端
if (requestId.equals(jedis.get(lockKey))) {
// 若在此时,这把锁突然不是这个客户端的,则会误解锁
jedis.del(lockKey);
}
}