使用redis实现分布式锁

使用redis实现分布式锁的主要原理是利用redis的原子性,有多个线程进行并发时只有一个线程可以设置成功

设置成功即获得了锁

如果出现异常,过了过期时间就直接释放

释放锁采用delete命令

释放锁之前要校验参数值,相同才能释放

@Slf4j
public class RedisLock implements AutoCloseable{
    private RedisTemplate redisTemplate;
    private String key;
    private String value;
    private int expireTime;

    public RedisLock(RedisTemplate redisTemplate, String key, int expireTime) {
        this.redisTemplate = redisTemplate;
        this.key = key;
        this.value = UUID.randomUUID().toString();
        this.expireTime = expireTime;
    }

    public Boolean lock() {
        log.info("我进入了方法");
        RedisCallback<Boolean> redisCallback = connection -> {
            // 设置NX
            RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
            // 超时时间
            Expiration expiration = Expiration.seconds(expireTime);
            byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);
            byte[] redisValue = redisTemplate.getValueSerializer().serialize(value);
            Boolean result = connection.set(redisKey, redisValue, expiration, setOption);
            return result;
        };
        Boolean lock = (Boolean)redisTemplate.execute(redisCallback);
        return lock;
    }

    public Boolean unLock() {
        String script = "if redis.call(\"get\", KEYS[1]) == ARGV[1] then\n" +
                "  return redis.call(\"del\", KEYS[1])\n" +
                "else\n" +
                "  return 0\n" +
                "end";
        List<String> keys = Arrays.asList(key);
        RedisScript<Boolean> redisScript = RedisScript.of(script, Boolean.class);
        // 释放锁的结果
        Boolean result = (Boolean)redisTemplate.execute(redisScript, keys, value);
        return result;
    }

    @Override
    public void close() throws Exception {
        unLock();
    }
}

在业务代码中使用redis分布式锁

@Service
public class RedisLockService {
    @Autowired
    private RedisTemplate redisTemplate;

    public String operation() {
        try (RedisLock redisLock = new RedisLock(redisTemplate, "redisKey", 30)) {
            // 如果成功获取锁
            if (redisLock.lock()) {
                // 执行业务代码
                Thread.sleep(15000);
                return "success";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 没获取到锁,返回失败
        return "fail";
    }
}

使用redission分布式锁

首先在pom文件中依赖redission

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.11.2</version>
</dependency>

使用redission自带的分布式锁

@Service
@Slf4j
public class RedisLockService {
    @Autowired
    private RedissonClient client;

    public String redissionLock() {
        RLock rLock = client.getLock("order");
        rLock.lock(30, TimeUnit.SECONDS);
        log.info("我获取到了锁!!!");
        try {
            Thread.sleep(10000);
            return "success";
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            log.info("我释放了锁!!!");
            rLock.unlock();
        }
        return "fail";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值