Redis实现分布式锁3-使用LUA脚本实现分布式锁,解决原子性问题
private static final Long SUCCESS = 1L; private static String script1 = "if redis.call('setNx',KEYS[1],ARGV[1]) then " + " if redis.call('get',KEYS[1])==ARGV[1] then " + " return redis.call('expire',KEYS[1],ARGV[2]) " + " else " + " return 0 " + " end " + "end"; private RedisScript<String> lockRedisScript1 = new DefaultRedisScript<>(script1, String.class); private static String script2 = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; private RedisScript<String> unLockRedisScript = new DefaultRedisScript<>(script2, String.class); /** * 获取锁 * * @param lockKey redis的key * @param value redis的value要求是随机串,防止释放其他请求的锁 * @param expireTime redis的key 的过期时间 单位(秒) 防止死锁,导致其他请求无法正常执行业务 * @return */ @Override public boolean lock(String lockKey, String value, long expireTime) { //对非string类型的序列化 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); Object result = redisTemplate.execute(lockRedisScript1, Collections.singletonList(lockKey), value, String.valueOf(expireTime)); return SUCCESS.equals(result); } /** * 释放锁 * * @param lockKey redis的key * @param value redis的value 只有value比对一致,才能确定是本请求 加的锁 才能正常释放 * @return */ @Override public boolean unlock(String lockKey, String value) { try { Object result = redisTemplate.execute(unLockRedisScript, Collections.singletonList(lockKey), value); if (SUCCESS.equals(result)) { return true; } } catch (Exception e) { e.printStackTrace(); } return false; }