Redis分布式锁是一种在分布式系统中协调多个进程对共享资源访问的同步机制。在单机系统中,可以使用传统的锁机制来保证同一时间只有一个线程访问某个资源。然而,在分布式系统中,由于多个进程可能在不同的服务器上运行,传统的锁机制就不再适用。这时就需要一种跨多个进程的锁机制,即分布式锁。
分布式锁应具备的特性:
- 互斥性:在任意时刻,只有一个进程可以持有锁。
- 安全性:锁需要保证在分布式系统中的安全性,即使在网络分区或其他故障情况下也能正常工作。
- 死锁容错性:即使在某个进程异常或宕机的情况下,锁也能被其他进程获取。
- 性能:加锁和解锁操作应该尽可能快,以避免影响系统性能。
- 可重入性:同一个进程可以多次获取同一把锁。
- 锁超时:锁需要有一个超时时间,以避免因为某些原因导致锁无法释放。
Redis分布式锁的实现方式:
-
SETNX + EXPIRE:使用
SETNX
命令设置键,如果键不存在则设置成功,然后使用EXPIRE
设置键的过期时间。但这种方式不是原子操作,可能存在安全问题。 -
SET命令扩展:使用
SET key value EX seconds PX milliseconds NX
命令,其中EX
和PX
分别设置键的过期时间(秒和毫秒),NX
表示只有键不存在时才设置。 -
Lua脚本:使用Lua脚本保证加锁操作的原子性,减少因进程崩溃导致锁无法释放的风险。
-
Redisson框架:Redisson是一个基于Redis的Java框架,提供了多种分布式数据结构和服务,包括实现分布式锁的功能。Redisson使用看门狗机制来自动续期锁,避免锁过期。
-
Redlock算法:由Redis作者提出的一种算法,使用多个Redis master节点来实现高安全性的分布式锁。客户端尝试在多个Redis实例上加锁,如果大多数实例加锁成功,则认为锁获取成功。
使用场景:
- 秒杀活动:确保同一时刻只有一个用户可以成功下单。
- 订单处理:在处理订单时,确保同一订单不会同时被多个进程处理。
- 库存管理:在库存有限的情况下,防止超卖。
注意事项:
- 锁的超时时间应该根据业务逻辑的执行时间来合理设置。
- 在分布式锁实现时,需要考虑到网络分区、节点故障等异常情况。
- 释放锁时,需要确保只有加锁的进程可以释放锁,避免安全问题。
Redis分布式锁由于其高性能和易用性,在现代分布式系统中得到了广泛应用。然而,正确实现分布式锁需要仔细考虑各种异常情况,以确保系统的稳定性和数据的一致性。下面给大家介绍一种现在比较常用的redis分布式锁,基于Redission实现分布式锁。
基于Redission实现分布式锁
使用Redission分布式锁,保障在分布式的条件下,可以锁住多个线程,不会因为做了Nginx负载均衡之后,导致被同步锁锁住的资源被其他服务器的进程当中的线程所访问。
通过SetNX实现分布式锁的话,它主要是通过SetNX设置一个键,如果这个键没有值则表示加锁成功,如果有值则表示当前的锁不可用。使用SetNX的时候,一定一定要加一个过期时间,因为如果不加过期时间,当这个服务器挂了之后,则会导致这个锁一直被占用,从而导致一个死锁的问题。
使用SetNX有一个很大的弊端,即如果业务的处理时间超过了锁的过期时间,那么当过期时间到了,即使业务未处理完,整个锁也会被释放,其他的线程便会来使用这把锁,整体的业务流程就会出现很大的问题。这时可以通过增加业务时间,和设置一个子线程每隔一段时间查看业务线程是否还在,在的话就自动增加过期时间,这个实现起来十分困难。
因此,redis提供了这个redission组件,来实现了上述的功能。下面为Redisson的实现原理,即获取锁,然后获取成功之后,便会执行相关业务,同时由于看门狗机制的存在,它会自动检测该线程是否还持有锁。
并且为了保证redis在分布式集群中的数据一致性的问题,redisson还提供了一个Redlock机制,用来保证主从结点之间的数据强一致性问题。如果未使用redlock,则在主节点数据操作完成后,便会响应一个操作成功,而使用redlock的话,只有当所有的主从节点都把相关数据操作完成后,才会响应一个操作成功,达到了数据强一致性的目的。
分布式锁在当前的主流业务中十分的常见,有时候还会配合相关的消息队列一同来实现相关的功能。Redission的分布式锁实现起来十分简单,只需导入相关依赖后,通过一个try.lock便可实现对资源的上锁。
笔者小,中,大厂均有面试经验,目前正在从事全栈开发工作,坚持每日分享java全栈开发知识与相关的面试真题,希望能够给大家带来帮助,同大家共同进步。
标签:加锁,实现,Redis,过期,线程,进程,分布式 From: https://blog.csdn.net/qq_56438516/article/details/141280279