1. 程式人生 > >redis setnx解決定時任務多節點部署併發問題(分散式鎖)

redis setnx解決定時任務多節點部署併發問題(分散式鎖)

在一些大的網際網路平臺,通常都會使用定時任務處理一些週期性的業務,而為了保障系統的高可用性,定時任務也會多節點部署,而解決多節點併發問題(分散式鎖),大家通常會想到使用快取,如redis,但是如果使用set / get是無法解決問題的,同樣會出現併發問題,redis有專門的解決分散式併發問題的方法,就是setnx命令,很好用,下面介紹一下java實現redis分散式鎖的方法。

1. Redis SETNX命令語法:

SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡寫,其操作為:將 key 的值設為 value ,當且僅當 key 不存在。若給定的 key 已經存在,則 SETNX 不做任何動作。
返回值:
  設定成功,返回 1 。
  設定失敗,返回 0 。

 SetNX 不具備設定過期時間的功能,所以我們需要藉助 Expire 來設定,否則可能會出現死鎖問題。

2. 環境說明

是基於 spring boot的專案,這是一個專案中多節點定時扣費任務的實現。

3. 配置實現

3.1. 定時任務

@Component
@EnableScheduling
public class QuartzCharge {
	Logger logger = LogManager.getLogger("quartzCharge");
	@Autowired
	RedisComponent redisComponent;
	
	
	 //每每小時0分0秒執行一次
     @Scheduled(cron = "0 0 * * * *")
	 public void quartzCharge(){
		 //需要先查詢redis的計費標記,如果有,就不計費,如果沒有就計費,整點計費
		 logger.info(" 定時計費開始: ");
		 //redis分散式鎖,儘量要設定過期時間,防止死鎖
		 if(!redisComponent.setNX("quartzChargeTag", "1", 10, TimeUnit.SECONDS)){
			 logger.info("已有執行中定時扣費任務,本次不執行!");
			 return;
		 }
		 
		 //計費
		 try{
			 //to_do 定時業務實現
             
		 }catch(Exception e){
			 logger.error("定時扣費異常結束: " + e);
		 }finally{
			//任務執行完,一定要清空快取,防止意外終止死鎖
			 redisComponent.del("quartzChargeTag");
		 }
		 
		 logger.info("定時計費結束!");
	 }

}

3.2.redis操作工具類

@Component
public class RedisComponent {
	@Autowired
	//操作字串的template,StringRedisTemplate是RedisTemplate的一個子集
	private StringRedisTemplate stringRedisTemplate;
	@Autowired
	// RedisTemplate,可以進行所有的操作  
	private RedisTemplate<Object,Object> redisTemplate;
	
	
	/*
	 * redis分散式鎖實現,同時利用expire設定過期時間
     * 返回true就是設定成功
	 * */
	public Boolean setNX(String key, String value,long timeout, TimeUnit unit){
		Boolean isExit = this.redisTemplate.getConnectionFactory().getConnection().setNX(key.getBytes(), value.getBytes());
		//如果設定成功,要設定其過期時間
        if(isExit){
			redisTemplate.expire(key, timeout, unit);
		}
		return isExit;
	}
	
}

3.3 雙節點執行效果

節點一日誌:

節點二日誌:

 

看兩個節點的日誌,可以清楚的看到,兩個節點相互執行定時任務,執行時間就在毫釐之間,誰快誰就搶到鎖,一個節點掛了還有另外一個,這樣就保障了系統的高可用,是不是挺酸爽的,O(∩_∩)O哈哈~

----------over--------------