Redis分布式锁

Redis 可以使用它的原子操作实现分布式锁,基本思路是在 Redis 中创建一个键值对,其中键表示锁的名称,值表示锁的持有者和过期时间。如果多个线程或进程尝试获取同一个锁,则只有一个线程或进程能够成功获取锁,其他线程或进程需要等待锁的释放。

以下是 Redis 实现分布式锁的简单场景示例代码:

public class RedisDistributedLock {

    private Jedis jedis;
    private String lockKey;
    private int expireTime = 60; // 锁的默认过期时间(秒)
    private int timeout = 10; // 尝试获取锁的超时时间(秒)
    private boolean locked = false; // 是否已经获取到了锁

    public RedisDistributedLock(Jedis jedis, String lockKey) {
        this.jedis = jedis;
        this.lockKey = lockKey;
    }

    public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
        this(jedis, lockKey);
        this.expireTime = expireTime;
    }

    public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime, int timeout) {
        this(jedis, lockKey, expireTime);
        this.timeout = timeout;
    }

    /**
     * 尝试获取锁,如果获取成功返回 true,否则返回 false
     */
    public boolean tryLock() {
        long start = System.currentTimeMillis();
        while ((System.currentTimeMillis() - start) / 1000 < timeout) {
            // 尝试设置锁的值,如果成功则返回 true
            String result = jedis.set(lockKey, String.valueOf(System.currentTimeMillis() + expireTime), "NX", "EX", expireTime);
            if ("OK".equals(result)) {
                locked = true;
                return true;
            }
            try {
                Thread.sleep(100); // 等待一段时间后再重试
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        return false;
    }

    /**
     * 释放锁
     */
    public void unlock() {
        if (locked) {
            jedis.del(lockKey);
            locked = false;
        }
    }

}

tryLock 方法尝试获取锁,如果获取成功则返回 true,否则返回 false。在 tryLock 方法中,使用 Redis 的 set 方法来设置锁的值。如果设置成功,说明当前线程或进程获得了锁,设置失败则说明其他线程或进程已经持有了锁。为了避免死锁,需要设置锁的过期时间,如果持有锁的线程或进程意外退出,锁会在过期时间之后自动释放。

unlock 方法用于释放锁,只有获得锁的线程或进程才能够释放锁。在 unlock 方法中,使用 Redis 的 del 方法删除锁的键值对。

注意:Redis 分布式锁也存在一些问题,例如死锁、误删除等。

 如何避免这些问题?

1、死锁:如果一个线程或进程在获取锁之后挂了,其他线程或进程会一直等待该锁的释放,导致死锁。为了避免死锁,需要设置合理的锁超时时间,当锁超时后自动释放。

2、误删除:如果一个线程或进程在释放锁之前,锁的超时时间已经过期,那么其他线程或进程可能会误认为该锁已经被释放,从而删除了该锁的键值对,导致其他线程或进程无法获得锁。为了避免误删除,可以在释放锁时先判断当前线程或进程是否持有该锁。

3、粗粒度锁:Redis 分布式锁只能实现粗粒度锁,无法实现细粒度锁。例如,如果需要锁定一条记录的某个字段,使用 Redis 分布式锁无法实现,需要使用其他方式实现。

4、高并发性能:Redis 分布式锁在高并发场景下可能会存在性能问题,需要合理设置锁的超时时间,并使用高性能的 Redis 集群。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值