Redis实现分布式锁1
Jedis结合setNX方法实现分布式锁
public boolean lock(String key, int exprie) { try { exprie = exprie <= 0 ? 60 : exprie; String value = JsonUtil2.obj2String(createMeta(exprie)); String lockKey = this.getLockKeyPrev() + key; String result=this.setNX(lockKey, value,"EX",exprie); if (result!=null && result.equals("OK")) { LOGGER.info("Get redis lock success, key =" + lockKey); return true; } Object obj = this.get(lockKey); if (obj==null) { this.delete(lockKey); LOGGER.info("Redis unlock success ,key = " + lockKey); Thread.sleep(1000); value = JsonUtil2.obj2String(createMeta(exprie)); String result1=this.setNX(lockKey, value,"EX",exprie); if (result1!=null && result1.equals("OK")) { this.expire(lockKey, exprie); LOGGER.info("Get redis lock success, key =" + lockKey); return true; } else { LOGGER.warn("Get redis lock fail, key =" + lockKey); return false; } } value = (String)obj; LockModel model = JsonUtil2.getObjectMapper().readValue(value, LockModel.class); if (model.isLose()) {// 已经超时 this.delete(lockKey); value = JsonUtil2.obj2String(createMeta(exprie)); String result2=this.setNX(lockKey, value,"EX",exprie); if (result2!=null && result2.equals("OK")) { this.expire(lockKey, exprie); LOGGER.info("Get redis lock success, key =" + lockKey); return true; } else { LOGGER.warn("Get redis lock fail, key =" + lockKey); return false; } } LOGGER.warn("Get redis lock fail, key =" + lockKey); return false; } catch (Exception ex) { ex.printStackTrace(); LOGGER.error(ex.getMessage()); return true; } } public void unlock(String key) { String lockKey = this.getLockKeyPrev() + key; try { delete(lockKey); } catch (Exception ex) { LOGGER.error(ex.getMessage()); } LOGGER.info("Redis unlock success ,key = " + lockKey); } private LockModel createMeta(int exprie) { LockModel meta = new LockModel(); meta.setExpireTime(exprie); meta.setLockTime(System.currentTimeMillis()); return meta; } public String getLockKeyPrev() { return "lock:"; } /** * 设置key * 需要传入key是否不存存在 * * @param key 键 * @param value 值 * @param expx EX/PX 值只能取EX或者PX,代表数据过期时间的单位,EX代表秒,PX代表毫秒 * @param interval 过期时间,单位是expx所代表的单位。 * @return SET 在设置操作成功完成时,才返回 OK 。 * 如果设置了 NX 或者 XX ,但因为条件没达到而造成设置操作未执行,那么命令返回空批量回复(NULL Bulk Reply) */ public String setNX(String key, Object value, String expx, long interval) { Jedis jedis = MyRedisPool.getJedis(); String result = ""; try { result = jedis.set(key, String.valueOf(value), "NX", expx, interval); } catch (Exception e) { e.printStackTrace(); } finally { MyRedisPool.returnResource(jedis); } return result; } /** * 删除给定的一个或多个 key 。 * 不存在的 key 会被忽略。 * * @param key 键 * @return 被删除 key 的数量。 */ public Long delete(String key) { Jedis jedis = MyRedisPool.getJedis(); Long result = 0L; try { result = jedis.del(key); } catch (Exception e) { e.printStackTrace(); } finally { MyRedisPool.returnResource(jedis); } return result; } /** * 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。 * 可以对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。 * * @param key * @param interval * @return 设置成功返回 1 。 * 当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。 */ public Long expire(String key, int interval) { Jedis jedis = MyRedisPool.getJedis(); Long result = 0L; try { result = jedis.expire(key, interval); } catch (Exception e) { e.printStackTrace(); } finally { MyRedisPool.returnResource(jedis); } return result; } /** * 返回 key 所关联的字符串值 * 如果 key 不存在那么返回特殊值 nil 。 * * @param key * @return 当 key 不存在时,返回 nil ,否则,返回 key 的值。 * 如果 key 不是字符串类型,那么返回一个错误。 */ public Object get(String key) { Jedis jedis = MyRedisPool.getJedis(); Object o = null; try { o = jedis.get(key); } catch (Exception e) { e.printStackTrace(); } finally { MyRedisPool.returnResource(jedis); } return o; }