最近项目中用到了redis数据过期监听的功能,当单机的时候,很完美的完成了业务要求,但是,一上集群,就产生了恶心的问题,它会产生广播效应,显然这不是我们想要的结果,我们只希望集群中某一个工程去监听这个过期事件然后进行下一步操作。

下面介绍一下我们在解决这个问题时锁采取的方式:

 

方案:利用redis的getset 命令方法进行解决;

 

思路是:在过期回调事件中利用getset设置 [ key(当前监听到的过期key)+".lock"作为新的key ], 字符串"1"作为value,当某一个工程触发回调事件时,由于时第一次进入,此时 getset方法返回null(),由于redis是单线程,所以其他工厂虽然也到了这个方法这里,但是此时getset时返回的是我们设置的value值,所以通过判断,如果“1”.equals(返回的value)直接return掉,不往下执行,如果 ! “1”.equals(返回的value)则往下执行;当下面的步骤都执行完成了,再从redis删除掉这条数据,因为每一次过期回调都会利用getset产生一条数据,以免数据量多大造成积压;

一、redis的getset命令介绍:

 

1、getset命令自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,返回错误。

2、getset命令返回之前的旧值,如果之前Key不存在将返回null。

 

二、我们采用的是RedisTemplate操作redis,以下是封装的redisUtil中的getset方法内容:

 

public  <T> T getAndSet(final String key, T value) {
		T oldValue = null;
		try {
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			oldValue =(T) operations.getAndSet(key, value);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return oldValue;
}

 

三、过期监听中getset代码实现:

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐