redis实现分布式锁,lua脚本实现上锁原子操作

  • 基础操作
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 使用Lua脚本的好处
    1、 一次性发送多个命令,减少网络开销。(是多个reids命令的集合,不用每次都去建立连接)
    2、原子性 (redis会将这个lua脚本认为是一个整体去执行,不会被打断,所以保证原子性)
    3、lua 文件复用 (命令非常多,可以放在一个文件中,这样其他的redis也可以调用,使其复用)

  • 基本用法

127.0.0.1:6379> eval "return 'hello world'" 0
"hello world"
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> eval "return redis.call('set',KEYS[1],ARGV[1])" 1 HZ 2222
OK
127.0.0.1:6379> keys *
1) "HZ"
127.0.0.1:6379> get hz
(nil)
127.0.0.1:6379> get HZ
"2222"
127.0.0.1:6379> 
  • demo
import lombok.extern.slf4j.Slf4j;
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.Collections;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class RedisUtil {

    /**
     * 获取锁的value,判断是否等于期待的value,满足的话,则删除该锁,并返回1;否则直接返回-1。
     */
    private static final DefaultRedisScript<Long> UNLOCK_LUA_SCRIPT = new DefaultRedisScript<>(
            "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return -1 end", Long.class
    );

    @Autowired
    private StringRedisTemplate redisTemplate;

	/**
     * 上锁
     * @param key			键
     * @param value			值
     * @param expireTime	失效时间
     * @param timeUnit		时间单位
     * @return
     */
    public boolean tryLockTime(String key, String value, long expireTime, TimeUnit timeUnit) {
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, timeUnit);
        if (flag == null || !flag) {
            log.error("申请锁(" + key + "," + value + ")失败");
            return false;
        }
        return true;
    }

    /**
     * 解锁
     *
     * @param key   键
     * @param value 值
     */
    public void unLockTime(String key, String value) {
        Long result = redisTemplate.execute(UNLOCK_LUA_SCRIPT, Collections.singletonList(key), value);
        if (result == -1) {
            log.error("释放锁(" + key + "," + value + ")失败,该锁不存在或锁已经过期");
        }
    }
}

  • 上锁
Boolean flag = redisUtil.tryLockTime("key", "value", 180, TimeUnit.SECONDS);
  • 解锁
redisUtil.unLockTime("key", "value");
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值