使用Redis实现分布式锁
public class JedisLock { private Jedis jedis; private String lockKey; /**默认过期时间*/ private int expireMillis = 3000; private String lockValue; public JedisLock(Jedis jedis, String lockKey){ this.jedis = jedis; this.lockKey = lockKey; } public boolean lock() throws InterruptedException{ return lock(1); } public boolean lock(int timeout) throws InterruptedException{ while(timeout > 0){ long expireTm = System.currentTimeMillis()+expireMillis; String expireTmStr = String.valueOf(expireTm); if(jedis.setnx(lockKey, expireTmStr)==1){ lockValue = expireTmStr; return true; } String currentValueStr = jedis.get(lockKey); if(currentValueStr!=null && Long.parseLong(currentValueStr)<System.currentTimeMillis()){ String oldValueStr = jedis.getSet(lockKey, expireTmStr); if(oldValueStr!=null && oldValueStr.equals(currentValueStr)){ lockValue = expireTmStr; return true; } } timeout -= 100; Thread.sleep(100); } return false; } public void unlock(){ List<String> keys = new ArrayList<String>(); keys.add(lockKey); List<String> args = new ArrayList<String>(); args.add(lockValue);
//采用lua脚本方式保证在多线程环境下也是原子操作 jedis.eval( "if (redis.call('exists', KEYS[1]) == 0) then " + "return -1; " + "end;" + "if (redis.call('get', KEYS[1]) == ARGV[1]) then " + "redis.call('del', KEYS[1]); " + "return 1;" + "end; " + "return 0;" , keys, args); } }