基于设计模式,实现分布式锁的资源管理

org.redisson.api.RLock,是目前较为常见的分部署锁实现方式。我们的目的是实现自动管理锁的获取和释放。

但遗憾的是,RLock并不实现AutoCloseable接口,因此不能直接用在try-with-resources结构中。不过,我们可以通过创建一个包装类或者辅助方法,使得RLock的使用更加符合try-with-resources模式。这样做的好处是使得代码更加简洁,并且能够保证即使发生异常也能够正确释放资源。

1.实现代码

1.1包装类

复制代码
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import java.util.concurrent.TimeUnit;
/**
 * @Description: RLock并不实现AutoCloseable接口,因此不能直接用在try-with-resources结构中。
 * 创建一个包装类,使得RLock的使用更加符合try-with-resources模式。这样做的好处是使得代码更加简洁,并且能够保证即使发生异常也能够正确释放资源
 **/
@Slf4j
public class AutoCloseableLock implements AutoCloseable{

	/**
	 * 锁定请求
	 */
	private final String target;

	/**
	 * 要获取的锁。
	 */
	private final RLock lock;

	/**
	 *锁状态
	 */
	private final boolean locked;

	/**
	 * 获取锁的等待时长
	 */
	private static final int WAIT_TIME = 3;

	/**
	 * 占用锁的最大时长
	 */
	private static final int LEASE_TIME = 10;

	public AutoCloseableLock(RLock lock, String target) throws InterruptedException {
		this.lock = lock;
		// 尝试获取锁,并立即返回结果。如果获取成功,设置锁的自动释放时间。
		this.locked = lock.tryLock(WAIT_TIME,LEASE_TIME, TimeUnit.SECONDS);
		this.target = target;
	}

	public boolean isLocked() {
		log.info("=====redisson分布式锁,【{}】上锁成功=====",this.target);
		return this.locked;
	}

	@Override
	public void close() {
		if (this.locked && lock.isHeldByCurrentThread()) {
			log.info("=====redisson分布式锁,【{}】开锁成功=====",this.target);
			lock.unlock();
		}
	}
}

1.2参数枚举类

复制代码
public enum LockEnum {
	login("LOGIN", "用户登录请求");

	/**
	 * 锁前缀
	 */
	private final String prefix;

	/**
	 * 锁请求
	 */
	private final String target;

	LockEnum(String prefix, String target) {
		this.prefix = prefix;
		this.target = target;
	}

	public String getPrefix() {
		return prefix;
	}

	public String getTarget() {
		return target;
	}
}

1.3 类的使用

复制代码
try (AutoCloseableLock autoLock = new AutoCloseableLock(
				redissonClient.getLock(StrUtil.format("{}_{}", LockEnum.login.getPrefix(), username)),
				LockEnum.login.getTarget())) {
    if (autoLock.isLocked()) {
        // 成功获取锁,执行业务逻辑...
    } else {
        // 获取锁失败的处理逻辑...
    }
} catch (InterruptedException e) {
    Thread.currentThread().interrupt(); // 重新设置中断状态
    // 处理中断异常...
}

2设计模式讲解

在这个示例中,AutoCloseableLock包装了一个Lock对象,并确保了在try-with-resources语句结束时自动释放锁,这既体现了资源管理器模式的优势,也借助装饰器模式的理念,为Lock对象增加了自动资源管理的功能。

2.1 资源管理器(Resource Management)模式

资源管理器设计模式的核心思想是确保对于需要手动管理的资源(如文件、数据库连接或锁等),在使用完毕后能够自动释放,以避免资源泄漏。在Java中,try-with-resources语句是这一模式的一个体现,它要求资源实现AutoCloseable或Closeable接口。当try块执行完毕时,无论是正常完成还是因为异常退出,都会自动调用close()方法来释放资源。

AutoCloseableLock类通过实现AutoCloseable接口,使得锁资源可以在try-with-resources语句中自动管理,从而简化了锁的获取和释放过程,减少了编码错误导致的资源泄漏风险。

2.2 装饰器(Decorator)模式

装饰器设计模式允许向一个对象添加新的功能,而不改变其结构。这是通过创建一个包含了原始对象的新对象来实现的,即"装饰"了原始对象。在AutoCloseableLock的上下文中,虽然它的主要目的不是为了添加新功能,但它通过包装Lock对象,并在此基础上添加了自动资源管理的功能,从某种角度来看,也体现了装饰器模式的思想。

相关推荐
cijiancao7 小时前
23 种设计模式中的解释器模式
java·设计模式·解释器模式
南七行者7 小时前
对模板方法模式的理解
java·设计模式·模板方法
高铭杰8 小时前
Citus源码(2)分布式读流程分析与基础概念梳理(shardid、placementid、groupid)
数据库·分布式·postgresql·citus
fallwind_of_july8 小时前
java项目分享-分布式电商项目附软件链接
java·redis·分布式·mongodb·elasticsearch·微服务·rabbitmq
郭涤生8 小时前
第七章:从类库到服务的分布式基石_《凤凰架构:构建可靠的大型分布式系统》
笔记·分布式·架构
郭涤生11 小时前
第十三章:持久化存储_《凤凰架构:构建可靠的大型分布式系统》
笔记·分布式·架构·系统架构
死磕java的孤行者11 小时前
Git 分布式版本控制工具
分布式·git·elasticsearch
郭涤生12 小时前
Chapter 12: The Future of Data Systems_《Designing Data-Intensive Application》
笔记·分布式
老大白菜13 小时前
Python FastAPI + Celery + RabbitMQ 分布式图片水印处理系统
分布式·python·fastapi
信徒_13 小时前
Kafka 中,为什么同一个分区只能由消费者组中的一个消费者消费?
分布式·kafka