基于缓存实现分布式锁

文章目录


前言

参考文章:

分布式锁的几种简单实现方式分析_基于缓存实现分布式锁的实现方式有-优快云博客

Redis分布式锁的实现方式、实现原理 - 知乎


提示:以下是本篇文章正文内容,下面案例可供参考

一、Redis缓存是什么?

                                                 高性能--高并发

  • Redis是一个内存数据库,通过将数据存储在内存中而非磁盘,能够实现极快的读写速度。
  • Redis使用数据结构,如字符串、哈希、列表等,以便快速访问所需数据,通常用键值对<key,value>来表示。
  • Redis采用单线程模型,避免了多线程竞争带来的复杂性,从而进一步提高了性能。
  • Redis 除了做缓存之外,也经常用来做分布式锁,消息队列。

二、实现过程

1.思路

在Redis中,可以使用SETNX命令来实现基本的分布式锁。SETNX命令会尝试在缓存中设置一个键值对,如果键不存在,则设置成功并返回1;如果键已存在,则设置失败并返回0。

还需要考虑:

  • 缓存的持久性: 确保锁在系统重启或缓存失效时能够正确恢复。
  • 缓存的过期时间: 可以为锁设置了一个过期时间,以防止节点在获取锁后崩溃或异常退出,导致锁一直无法释放。设置合理的过期时间可以避免锁长时间占用而导致的资源浪费。
  • 锁的安全释放:在使用Redis的DEL命令来删除锁时,需要确保操作的原子性,避免误删其他节点持有的锁,避免造成多线程或多节点情况下的并发问题。我们可以引入一个计数器,记录某个线程获取锁的次数。当线程再次尝试获取锁时,只有计数器为0时才会真正获取锁,否则只会增加计数器。释放锁时,计数器减少,直到为0才真正释放锁。
  • 缓存的一致性:在使用多个缓存节点时,确保它们之间存储的数据保持一致性。由于缓存可能会存储临时数据,因此在多个节点同时访问和修改数据时,保持数据的准确性和一致性变得尤为重要。可以选择使用Redis的集群模式或者使用分布式锁库,确保锁在多个节点间的一致性。

2.代码

代码如下(示例):


public class DistributedLockForRedis {
    private static final String REDIS_HOST = "localhost";
    private static final int REDIS_PORT = 6379;
 
    // 获取锁
    public static boolean acquireLock(String lockName, int timeout) {
        Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);
        long startTime = System.currentTimeMillis();
        while (true) {

 //Redis命令解释:NX:表示如果锁不存在则设置成功。EX:表示设置锁的过期时间为timeout秒。

            String result = jedis.set(lockName, "holder", "NX", "EX", timeout);
            if (result != null && result.equalsIgnoreCase("OK")) {
                // 成功获取到锁
                return true;
            } else if (System.currentTimeMillis() - startTime > timeout) {
                // 超时退出
                return false;
            } else {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // 线程被中断
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
 
    // 释放锁
    public static void releaseLock(String lockName) {
        Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);
        jedis.del(lockName);
    }
 
    // 使用锁
    public static void doSomethingWithLock() {
        String lockName = "my_lock";
        if (acquireLock(lockName, 5000)) {
            try {
                // 执行需要加锁的操作
                System.out.println("Lock acquired. Doing something...");
                Thread.sleep(5000);
                System.out.println("Finished.");
            } catch (InterruptedException e) {
                // 线程被中断
                Thread.currentThread().interrupt();
            } finally {
                releaseLock(lockName);
            }
        } else {
            System.out.println("Failed to acquire lock.");
        }
    }
 
    // 主程序
    public static void main(String[] args) {
        doSomethingWithLock();
    }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值