private final static int INIT_VERSION = 2;/*** 单位为毫秒; 获取的锁的自动释放时间是100ms.*/private final static int DEFAULT_EXPIRE_TIME = 100;/*** 单位为毫秒; 获取锁时, 默认的等待时间. 重试次数计算: DEFAULT_TIMEOUT/DEFAULT_LOCK_RETRY_INTERVAL*/private final static int DEFAULT_TIMEOUT = 200;/*** 单位为毫秒; 获取锁时, 默认重试的时间间隔是50ms.*/private final static int DEFAULT_LOCK_RETRY_INTERVAL = 50;/*** 释放锁时, 默认进行五次重试.*/private final static int DEFAULT_UNLOCK_RETRY_COUNT = 5;private ThreadLocal<String> threadValue = new ThreadLocal<String>();@Overridepublic boolean lock(String key) {return lock(key, DEFAULT_EXPIRE_TIME, DEFAULT_TIMEOUT);}@Overridepublic boolean lock(String key, int expireTime, long timeout) {long start = System.currentTimeMillis();for (; ; ) {boolean rs = tryLock(key, expireTime);if (rs) {return true;}long current = System.currentTimeMillis();if ((current - start + DEFAULT_LOCK_RETRY_INTERVAL) > timeout) {LOG.error("lock timeout. key:{}", key);return false;}waitToRetry();}}@Overridepublic boolean tryLock(String key, int expireTime) {try {DataEntry<String> dataEntry = super.get(key);// 如果已经有值, 则判断是否是重入场景if (dataEntry != null && !StringUtils.isBlank(dataEntry.getValue())) {String value = dataEntry.getValue();return threadValue.get() != null && threadValue.get().equals(value);}// 如果没有值, 则设置值, 获取锁String value = threadValue.get();if (value == null) {value = generateValue();threadValue.set(value);}super.setWithVersion(key, value, INIT_VERSION, expireTime);return true;} catch (Exception e) {LOG.error("tryLock error. key:{}", key, e);return false;}}@Overridepublic boolean unlock(String key) {String value = threadValue.get();for (int i = 0; i < DEFAULT_UNLOCK_RETRY_COUNT; i++) {try {DataEntry<String> stringDataEntry = super.get(key);if (null != stringDataEntry && StringUtils.isNotBlank(stringDataEntry.getValue()) && StringUtils.isNotBlank(value) && StringUtils.equals(stringDataEntry.getValue(), value)) {super.remove(key);threadValue.remove();return true;} else {LOG.error("unlock error. key:{}", key);return false;}} catch (Exception e) {LOG.error("unlock error. key:{}", key, e);}}LOG.error("unlock fail after retry ${} times, tair service may be unavailable now", DEFAULT_UNLOCK_RETRY_COUNT);return false;}private void waitToRetry() {try {Thread.sleep(DEFAULT_LOCK_RETRY_INTERVAL);} catch (Exception e) {LOG.warn("waitToRetry error", e);}}private String generateValue() {return Thread.currentThread().getName() + "_" + UUID.randomUUID().toString();}
