【Redis分布式锁】

分布式锁概述

分布式锁是一种用于协调分布式系统中多个节点对共享资源访问的同步机制。在单机多线程环境下,我们可以使用Java中的ReentrantLock或synchronized等本地锁来控制线程对共享资源的访问。但在分布式系统中,不同的服务/客户端通常运行在独立的JVM进程上,本地锁无法跨JVM实现互斥访问,这时就需要分布式锁

Redis分布式锁基础实现

SETNX命令实现

Redis实现分布式锁的核心在于利用其"互斥"能力,主要通过SETNX(SET if Not eXists)命令实现。这个命令表示如果key不存在才会设置其值,否则不做任何操作。

基本实现流程:

# 加锁
127.0.0.1:6379> SETNX lockKey uniqueValue
(integer) 1  # 加锁成功

# 释放锁
127.0.0.1:6379> DEL lockKey
(integer) 1

这种简单实现存在严重问题:如果获取锁的客户端崩溃或网络中断,无法释放锁,将导致死锁。

Redisson

是Redis官方推荐的Java客户端之一,提供了丰富的分布式对象和服务,其中分布式锁是其核心功能之一。下面我将详细解析Redisson分布式锁的实现机制。

使用示例

  public void outer() {
        lock.lock();
        try {
            System.out.println("Outer method acquired lock");
            inner(); // 再次获取同一把锁
        } finally {
            lock.unlock();
            System.out.println("Outer method released lock");
        }
    }

    public void inner() {
        lock.lock(); // 再次获取同一把锁(重入)
        try {
            System.out.println("Inner method acquired lock");
        } finally {
            lock.unlock();
            System.out.println("Inner method released lock");
        }
    }
ThreadA Lock lock() (outer方法) 获得锁成功 调用inner方法 lock()(inner方法) 再次获得锁成功(重入) unlock()(inner方法) inner方法释放一次锁 unlock()(outer方法) outer方法释放一次锁(完全释放) ThreadA Lock

Redis分布式锁中lock_key

在分布式锁场景中,lock_key相同是设计上的​​必然要求​​,这是由分布式锁的基本原理决定的:

​​互斥性要求​​:所有客户端必须使用相同的key来竞争同一把锁
如果每个客户端使用不同的key,就失去了互斥的意义
例如:秒杀系统中的商品ID seckill:product:123

Redisson主从一致性

在Redis主从复制架构中,当客户端在主节点获取锁后,如果主节点在将锁信息同步到从节点前宕机,此时:

  • 从节点被提升为新主节点
  • 新客户端可能从新主节点获取相同的锁
  • 导致多个客户端同时持有同一把锁,破坏互斥性

Redisson的解决方案

1. Redlock算法实现

Redisson提供了RedLock(红锁)实现,基于Redis作者提出的Redlock算法:

  • 向N个独立的Redis节点顺序获取锁
  • 当且仅当获取到大多数节点(N/2+1)的锁时才算成功
  • 总耗时必须小于锁过期时间
  • 释放锁时需要向所有节点发送释放请求
Client Redis1 Redis2 Redis3 Redis4 Redis5 SET resource lock NX PX 10000 OK null alt [成功] [失败] SET resource lock NX PX 10000 OK null alt [成功] [失败] SET resource lock NX PX 10000 OK null alt [成功] [失败] SET resource lock NX PX 10000 OK null alt [成功] [失败] SET resource lock NX PX 10000 OK null alt [成功] [失败] 成功获取 >=3 个锁并在有效期内 → 加锁成功 否则,释放已加锁的 Redis DEL resource lock(如果已加锁) DEL resource lock(如果已加锁) DEL resource lock(如果已加锁) DEL resource lock(如果已加锁) DEL resource lock(如果已加锁) alt [加锁失败] Client Redis1 Redis2 Redis3 Redis4 Redis5
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
try {
    // 临界区代码
} finally {
    lock.unlock();
}
方案一致性保证性能实现复杂度适用场景
单Redis节点非关键业务
Redlock金融/交易
Zookeeper最强强一致需求
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值