redisTemplate分布式锁(lua加锁setNX)

加锁没有用lua脚本 感兴趣的可以试一下

set然后expire这种操作不是原子性的,所以高并发下存在问题
使用lua脚本原子加锁
最新的redis-template中也支持原子操作了setIfAbsent()
好像是redis2.6.12之后加入的(redisTemplate也是操作的jedis)
springboot2.1.*/spring-data-redis2.1.9+

    private static final Long SUCCESS = 1L;

	// NX -- 仅在不存在的情况下才设置密钥。 XX -- 仅设置已存在的密钥。
	private static final String NX = "NX";
	// 过期时间单位:EX = 秒; PX = 毫秒
	private static final String EX = "EX";

	private static final String LOCK_OK = "OK";

    private static RedisSerializer<String> argsSerializer = new StringRedisSerializer();

	private static RedisSerializer resultSerializer = new StringRedisSerializer();

	private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

   /**
	 * 是否存在
	 * @param key
	 * @param value
	 * @param expireSeconds
	 * @return true:加锁成功;false:已存在锁
	 */
	public boolean lock(String key, String value, long expireSeconds) {

		return  (boolean)redisTemplate.execute(new RedisCallback<Boolean>() {
			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				Object nativeConnection = connection.getNativeConnection();
				if (nativeConnection instanceof JedisCluster) {
					JedisCluster jedisCluster = (JedisCluster) nativeConnection;
					String result = jedisCluster.set(key, value, NX, EX, expireSeconds);
					return LOCK_OK.equals(result);
				}
				if (nativeConnection instanceof Jedis) {
					Jedis jedis = (Jedis) nativeConnection;
					String result = jedis.set(key, value, NX, EX, expireSeconds);
					return LOCK_OK.equals(result);
				}
				return false;
			}
		});

	}
   /**
	 * 解锁
	 *
	 * @param
	 * @param
	 * @return
	 */
	public Boolean unlock(String key, String value) {

		RedisScript<String> redisScript = new DefaultRedisScript<>(UNLOCK_SCRIPT, String.class);
		// argsSerializer,resultSerializer 需要传递,不然某种情况下执行不了
		Object result = redisTemplate.execute(redisScript, argsSerializer, resultSerializer, Collections.singletonList(key), value);

		if (SUCCESS.equals(result)) {
			return true;
		}

		return false;
	}

加锁 lua,解锁lua

-- 加锁
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
-- 解锁
if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值