Redis的复合SET命令和简易的分布式锁优化

文章探讨了在不引入额外框架的情况下,如何利用Redis的SET复合命令优化分布式锁,以解决并发执行和异常处理的问题。通过结合SET命令的EX、NX选项,实现了原子性的加锁操作,并给出了具体的Java代码示例。最后提醒在生产环境中应优先考虑使用成熟的分布式锁库,如Redisson。

前提

最近在跟进一个比较老的系统的时候,发现了所有调度任务使用了spring-context里面的@Scheduled注解和自行基于Redis封装的简易分布式锁控制任务不并发执行。为了不引入其他框架的情况下做一些简单优化,笔者花点时间去研读了一下Redis的SET命令的相关文档。

场景还原

使用@Scheduled注解实现定时任务,使用spring-data-redis提供的API实现简易的Redis分布式锁的伪代码如下:

// 每30分钟跑一次
@Scheduled(cron = "* */30 * * * ? ")
public void scheduledMethod(){
	// 判断KEY存在性并且设置KEY,带超时时间5分钟
	if (StringRedisTemplate#opsForValue()#hasKey("定时任务唯一字符串标识")){
		StringRedisTemplate#opsForValue()#set("定时任务唯一字符串标识", "1[这里暂时可以使用任何值]", 5 , TimeUnit.MINUTES);
	}
	// 这里做调度正常业务逻辑
	doBusiness();
	// 删除KEY
	StringRedisTemplate#opsForValue()#delete("定时任务唯一字符串标识");
}

上面的代码存在如下显然的缺陷:

  1. 如果应用部署多个节点,由于判断KEY的存在性和SET操作是两个操作(非原子操作),该定时任务有可能在同一个时刻并发执行多次。
  2. 如果业务逻辑执行方法doBusiness()抛出了异常,会导致删除KEY的操作无法执行,KEY会到达超时时间后被删除,这个时候相当于加锁时间长达5分钟,显然是无法接受的。

但是实际上,以上两个问题在生产环境中并没有出现过,分析一下具体原因是:

  • 对于第1点,该应用在生产环境只部署了2个节点,节点的重启时间并不相同,所以从天然上避免了重复执行的问题,如果CRON表达式设计
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值