首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

基础redis锁,防止任务并发

对于很多系统而言,都有集群处理。在集群中使用quartz或者task处理任务的时候,一般有三种选择:

1. 多实例顺序执行

2. 单实例执行

3. 多实例并行执行

对于2,需要单独的实例进行部署运行,如果任务较多,需要独立的资源耗费较多,对于执行任务的实例要求就更高。

对于3,需要成熟的数据驱动式的任务分配,防止多实例重复执行。

2和3会在后续分享中进行。

对于多实例,同一数据库的情况下。创保目前考虑的是1情况。

redis对于并发较小的情况下,进行锁控制,效果是较为理想的。目前创保只有八台实例,适用于该方案。

首先,redis提供了一个setnx方法,该方法执行后会返回key值在设置之前是否存在。

这是进行并发控制的基础,但并不够。

在利用setnx进行key值设定后,如果instance发生异常(不仅仅是exception)会导致该锁无法正常释放。

所以,我们需要为锁设置一个失效时间,即expire命令。

由于redis有顺序执行命令的特性,如果我们setnx方法与expire命令并不是以一个原子粒度执行的话,将会导致一些不可控的现象发生。

所以,我们使用了multi方法进行命令绑定,将setnx与expire进行绑定,保障同一原子粒度执行。

同时,为了避免不必要的设置损耗,同时为了兼容对于锁的value值进行特异设置的情况,我们进行了exists判断。

整体代码进行整合,方法如下:

public boolean setLock(String key, int seconds, String value)

throws BusinessServiceException {

boolean isBroken = false;

Jedis jedis = null;

try {

jedis = this.jedisPool.getResource();

boolean exists = jedis.exists(key);

if(exists) {

return false;

}

Transaction transaction = jedis.multi();

Response result = transaction.setnx(key, value);

transaction.expire(key, seconds);

transaction.exec();

return result.get() == 1;

} catch (Exception e) {

logger.error("redis getLock error" + e.getMessage());

logger.error(e);

return false;

} finally {

this.releaseJedis(jedis, isBroken);

}

}

同时,在使用该锁的时候,也有一些规范需要遵守。

在获取到锁之后,才能进行业务逻辑处理。

在业务逻辑处理之后,必须手动释放锁。

未获取到锁的instance不允许释放锁。

过期时间必须设置,推荐设置时间为业务逻辑执行时间的1.5倍左右或任务间隔的2~3倍左右。

示例代码如下:

boolean result = false;

try {

result = redisService.setLock(TIMER_NAME,EXPIRE_TIME,LOCK_STATUE);

} catch (BusinessServiceException e) {

logger.error("timer get redis lock error:"+e.getMessage(),e);

}

if(result){

try{

//此处执行业务逻辑

}catch(Exception e){

logger.error("syncPolicy error:"+e.getMessage(),e);

}finally{

try {

redisService.delRedisValue(TIMER_NAME);

} catch (BusinessServiceException e) {

logger.error("timer relase redis lock error:"+e.getMessage(),e);

}

}

}

对于2和3的方案,后续再进行分享。

领导说了

您点一个

小编的工资就涨五毛!

分享IT技术、汇集最新资讯

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180608G1872600?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券