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

猜你喜欢

转载自blog.csdn.net/qq_35035078/article/details/82736151
今日推荐