分散式 第2 篇 redis 分散式鎖
阿新 • • 發佈:2018-12-20
public interface IDistributedLock { boolean tryLock(String var1, Object var2); boolean tryLock(String var1, Object var2, int var3); boolean unLock(String var1, Object var2); }
ublic class DistributedLockImpl implements IDistributedLock { private static final String lockScript = "local n = redis.call('setnx',KEYS[1],ARGV[1])\nif n == 1 then redis.call('expire',KEYS[1],ARGV[2]) end\nreturn n"; @Autowired private RedisTemplate template; private Map<String, String> randomValueMap = new ConcurrentHashMap(); private int defaultExpireTime = 3; public DistributedLockImpl() { } public boolean tryLock(String busiType, Object key) { return this.tryLock(busiType, key, this.defaultExpireTime); } public boolean tryLock(String busiType, Object key, int expire) { return (Boolean)this.template.execute((jedis) -> { String lockKey = this.getLockKey(busiType, key); String lockValue = this.getLockValue(busiType, key); boolean locked = (Long)jedis.eval("local n = redis.call('setnx',KEYS[1],ARGV[1])\nif n == 1 then redis.call('expire',KEYS[1],ARGV[2]) end\nreturn n", 1, new String[]{lockKey, lockValue, String.valueOf(expire)}) > 0L; if (locked) { this.randomValueMap.put(lockKey, lockValue); } return locked; }); } public boolean unLock(String busiType, Object key) { return (Boolean)this.template.execute((jedis) -> { String lockedKey = this.getLockKey(busiType, key); String lockedValue = jedis.get(lockedKey); String localLockedValue = (String)this.randomValueMap.get(lockedKey); if (lockedValue == null) { this.randomValueMap.remove(lockedKey); return true; } else if (StringUtils.equals(lockedValue, localLockedValue)) { if (jedis.del(lockedKey) > 0L) { this.randomValueMap.remove(lockedKey); return true; } else { return false; } } else { return false; } }); } private String getLockKey(String busiType, Object key) { Objects.requireNonNull(busiType); Objects.requireNonNull(key); return busiType + "_" + key; } private String getLockValue(String busiType, Object key) { Objects.requireNonNull(busiType); Objects.requireNonNull(key); return "lock_" + busiType + "_" + key + "_" + (new SecureRandom()).nextInt(); } }
public class RedisTemplate { private IRedisClientMgr clientMgr; private String client = "default"; public RedisTemplate(IRedisClientMgr clientMgr) { Objects.requireNonNull(clientMgr); this.clientMgr = clientMgr; } public <T> T execute(RedisOperate<T> operate) { return this.clientMgr.getClient(this.client).executeCmd(operate); } public <T> T execute(RedisOperate<T> operate, String client) { return this.clientMgr.getClient(client).executeCmd(operate); } public void setClient(String client) { this.client = client; } }