package com.jarvis.cache.lock; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; /** * 基于Redis+Lua实现分布式锁; 实现方法更容易理解,但性能相对会差些 * @author jiayu.qiu */ public abstract class AbstractRedisLockWithLua implements ILock { /** * 分布式锁 KEY[1] lock key <br> * ARGV[1] 过期时间 ARGV[2] 缓存时长 返回值: 如果执行成功, 则返回1; 否则返回0 */ private static final String lockScriptStr="local lockKey= KEYS[1]\n"// + "local lock = redis.call('SETNX', lockKey, ARGV[1])\n" // 持锁 + "if lock == 0 then\n" // + " return 0\n" // + "end\n" // + "redis.call('EXPIRE', lockKey, tonumber(ARGV[2]))\n" // 持锁n秒 + "return 1\n"; private static byte[] lockScript; static { try { lockScript=lockScriptStr.getBytes("UTF-8"); } catch(Exception e) { e.printStackTrace(); } } protected abstract Long eval(byte[] lockScript, String key, List<byte[]> args) throws UnsupportedEncodingException; protected abstract void del(String key); @Override public boolean tryLock(String key, int lockExpire) { try { List<byte[]> args=new ArrayList<byte[]>(); long expire2=System.currentTimeMillis() + (lockExpire * 1000); args.add(String.valueOf(expire2).getBytes("UTF-8")); args.add(String.valueOf(lockExpire).getBytes("UTF-8")); Long rv=eval(lockScript, key, args); return null != rv && rv.intValue() == 1; } catch(Exception e) { e.printStackTrace(); } return false; } @Override public void unlock(String key) { try { del(key); } catch(Throwable e) { } } }