1. 程式人生 > >7 redis分散式鎖+redisson

7 redis分散式鎖+redisson

 redis分散式鎖解決叢集環境下的定時任務

需要特殊考慮的是,異常關機碟機而產生的死鎖(程式碼剛剛走到set的時候)
package com.mmall.common.schedule;


import lombok.extern.slf4j.Slf4j;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.mmall.util.RedisShardedPoolUtil;

@Component
public class ScheduleTest {

	
//	@Scheduled(cron="0/5 * * * * ?")
//	public void schbobo(){
//		Date date = new Date();
//        SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        String dateStr = sim.format(date);
//        log.info("這是spring定時器1,每五秒執行一次,當前時間:" + dateStr);
//        System.out.println("這是spring定時器1,每五秒執行一次,當前時間:" + dateStr);
//		
//	}
	
	//reids分散式鎖的定時任務
	@Scheduled(cron="0/5 * * * * ?")
	public void schbobo_1(){
		String key="bobodekey";
		Long setresult=RedisShardedPoolUtil.setNx(key,String.valueOf(System.currentTimeMillis()+50000));
		if(setresult!=null&&setresult.intValue()==1){
			System.out.println("我獲得到了鎖哦來自schbobo_1");
			//獲取鎖成功,並且進行業務操作
			add(key);
			System.out.println("結束了生命週期");
		}else{//為了防止異常碟機而產生的死鎖
			String oldKey=RedisShardedPoolUtil.get(key);
			if(oldKey!=null&&System.currentTimeMillis()>Long.parseLong(oldKey)){//已經超過vlued的有效期
				String getsetVlue=RedisShardedPoolUtil.getset(key, String.valueOf(System.currentTimeMillis()+50000));
				if(getsetVlue==null||getsetVlue.equals(oldKey)){
					add(key); 
				}
			}
			System.out.println("沒有獲取到鎖,我是schbobo_1裡面的else");
		}
	}
	
	
	/**
	 * 進行業務操作並且防止死鎖的發生
	 * @param key
	 */
	private void add(String key){
		//設定50秒的有效期
		RedisShardedPoolUtil.exPire(key,50);
		System.out.println("我做了好多事情唉,都做完了");
		RedisShardedPoolUtil.del(key);
	}
}
  • redisson

  • 官網redisson.org 
匯入架包:
<!-- redisson需要的架包 -->
		<dependency>
			<groupId>org.redisson</groupId>
			<artifactId>redisson</artifactId>
			<version>2.9.0</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-avro</artifactId>
			<version>2.9.0</version>
		</dependency>
編寫工具類獲取redisson例項
package com.mmall.util;

import javax.annotation.PostConstruct;

import lombok.extern.slf4j.Slf4j;

import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class RedissonManager {
	private Config config=new Config();
	private Redisson redisson=null;
	
	
	public Redisson getRedisson() {
		return redisson;
	}


	@PostConstruct
	private void init() {
		try {
			config.useSingleServer().setAddress("111.231.114.12:6379").setPassword("bobo");
			redisson=(Redisson)redisson.create(config);
			log.info("獲取redisson例項成功");
		} catch (Exception e) {
			log.info("獲取redisson例項失敗,error{}",e);
		}
	
	}
	

}
重新設計分散式鎖,使用redisson的可重入鎖解決分散式的定時任務
/**
	 * 使用redisson操作鎖
	 */
	@Scheduled(cron="0/5 * * * * ?")
	public void shcbobo_2(){
		String key="bobodekeyzuihouyige";
		RLock lock= RedissonManager.getRedisson().getLock(key);
		Boolean getlock=false;
		try {
			//第一個引數是等待多少秒,一般設定成0,因為無法估算業務執行完的一個時間,如果設定短了,就會被其他的進行獲取到鎖,所以設定成0,不進行等待
			//第二個引數是有效期50秒,超過50秒就會失效
			//第三個引數是單位是秒
			if(getlock=lock.tryLock(0,50,TimeUnit.SECONDS)){
				System.out.println("執行了業務");
			}else{
				System.out.println("沒有獲取到鎖");
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			if(!getlock){
				return;
			}
			//刪除鎖
			lock.unlock();
			System.out.println("刪除了鎖");
		}
}     
redis,主從配置,讀寫分離,哨兵模式
redis主從配置,配置master 只能為寫,slave只能為讀,在客戶端對poolconnect請求時候,,會將讀請求轉到slave上面,寫請求轉到master上面,同時,master和slave有同步功能,這就實現了(資料層)讀寫分離對上層(邏輯層)透明的正常邏輯。無需再通過中介軟體或者程式碼進行讀寫分析實現。
https://blog.csdn.net/zmx729618/article/details/76671746