什么是分布式锁定?
在多线程程序中,不同的线程可能需要访问相同的资源。但是,允许所有线程同时访问资源可能会导致竞争条件,错误和其他意外行为。
为了确保没有两个线程同时访问同一资源并且资源以可预测的顺序进行操作,程序员使用称为锁的机制。每个线程首先获取锁,对资源进行操作,最后将锁释放到其他线程。
在Java中,出于多种原因,锁定对象通常比使用同步块更灵活。首先,Lock API可以以不同的方式运行,而synchronized块完全包含在一个方法中。
此外,如果线程被阻止,则无法访问同步块。使用Lock,该线程只有在可用时才获取锁。这大大减少了线程等待的时间。此外,当线程正在等待时,可以调用一个方法来中断线程,这在线程等待获取同步块时是不可能的。
分布式锁定意味着您不仅需要考虑多个线程或进程,还需要考虑在不同计算机上运行的不同客户端。这些单独的服务器必须进行协调,以确保在任何给定时间只有其中一个服务器正在使用该资源。
基于Redis的分布式锁定工具
该Redisson框架是一个Redis的基于内存数据网格,对于谁需要执行分布式锁定程序员提供了多个对象。下面,我们将讨论每个选项以及它们之间的差异。
1.锁
该RLock接口实现了java.util.concurrent.locks.Lock接口。它是一个可重入的锁,这意味着线程可以多次锁定资源。计数器变量记录锁定请求的次数。一旦线程发出足够的解锁请求并且计数器达到0,就会释放资源。
以下简单的代码示例演示了如何在Redisson中创建和启动Lock:
如果获取此锁的Redisson实例崩溃,则锁可能会在此获取状态中永久挂起。为了避免这种情况,Redisson维持一个锁,当持有锁的Redisson实例仍然存活时,它会延长锁的到期时间。默认情况下,此锁监视程序的超时时间为30秒。可以通过Config.lockWatchdogTimeout设置更改此限制 。
Redisson还允许您指定leaseTime参数。在指定的时间间隔后,锁定将自动释放:
2. FairLock
RFairLock也实现了 java.util.concurrent.locks.Lock 接口。通过使用 FairLock,您可以保证线程将按照它们请求的顺序获取资源(即“先进先出”)。Redisson为在队列中的下一个线程解锁资源之前重启的线程提供了五秒钟的重启时间。
与此同时RLocks,创建FairLock是一个简单的过程:
3. ReadWriteLock
RReadWriteLock 实现了 java.util.concurrent.locks.ReadWriteLock接口,读/写锁实际上是两个锁的组合:可以由多个线程同时拥有的只读锁,以及一次只能由单个线程拥有的写锁。
创建RReadWriteLock的方法如下:
4. RedLock
该RedissonRedLock 对象实现了Redlock锁算法,以便在Redis中使用分布式锁:
在Redlock算法中,我们在单独的计算机或虚拟机上有许多独立的Redis主节点。该算法尝试使用相同的密钥名称和随机值顺序地获取每个实例中的锁。只有当客户端能够比锁定有效的总时间更快地从大多数实例获取锁定时,才会获取锁定。