package com.wosai.upay.job.biz; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Component; import java.util.Arrays; public class RedisLock { @Autowired private StringRedisTemplate redisTemplate; private final static DefaultRedisScript<Long> LOCK_LUA_SCRIPT = new DefaultRedisScript<>( "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end" , Long.class ); private final static DefaultRedisScript<Long> UNLOCK_LUA_SCRIPT = new DefaultRedisScript<>( "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" , Long.class ); public boolean lock(final String key, final String value, long timeInSeconds) { Long result = redisTemplate.execute(LOCK_LUA_SCRIPT, Arrays.asList(key), value, String.valueOf(timeInSeconds)); return result == 1; } public boolean unlock(String key, String value) { Long result = redisTemplate.execute(UNLOCK_LUA_SCRIPT, Arrays.asList(key), value); return result != null && result == 1; } }
if (!redisLock.lock(key, value,”时间“)) { return; } try { //做业务 } catch (Exception e) { //业务处理 } finally { redisLock.unlock(key, value); }
不加过期时间的写法:
public boolean lock(final String key, final String value, long waitTimeMillis, long expireSeconds) throws InterruptedException { boolean success = false; long alreadyWaitTime = 0; while (true) { try { Long result = 0L; if (expireSeconds != 0) { result = redisTemplate.execute(LOCK_LUA_SCRIPT_WITH_EXPIRE, Arrays.asList(key), value, String.valueOf(expireSeconds)); } else { result = redisTemplate.execute(LOCK_LUA_SCRIPT_NO_EXPIRE, Arrays.asList(key), value, String.valueOf(expireSeconds)); } success = (result == 1); } catch (Exception e) { log.warn("加锁失败:{}", key, e); } if (success) { return true; } if (alreadyWaitTime >= waitTimeMillis) { return false; } Thread.sleep(10L); alreadyWaitTime = alreadyWaitTime + 10; } } public boolean unlock(String key, String value) { Long result = redisTemplate.execute(UNLOCK_LUA_SCRIPT, Arrays.asList(key), value); return result != null && result == 1; } private final static DefaultRedisScript<Long> LOCK_LUA_SCRIPT_WITH_EXPIRE = new DefaultRedisScript<>( "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end" , Long.class ); private final static DefaultRedisScript<Long> LOCK_LUA_SCRIPT_NO_EXPIRE = new DefaultRedisScript<>( "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then return 1 else return 0 end" , Long.class ); private final static DefaultRedisScript<Long> UNLOCK_LUA_SCRIPT = new DefaultRedisScript<>( "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" , Long.class );
参考:RedisTemplate下Redis分布式锁引发的系列问题_redistemplate加锁其它写入有影响吗-CSDN博客