zoukankan      html  css  js  c++  java
  • 分布式redis锁的实现原理

    /** 
     * Project Name:demo-project-generator 
     * File Name:RedisLockBase.java 
     * Package Name:com.gomeplus.market 
     * Date:2017年8月7日上午10:16:23 
     * Copyright (c) 2017, suchao@gomeplus.com All Rights Reserved. 
     * 
    */  
    
    package cn.com.gome.game.rocket.client.base;
    
    import java.util.Date;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import redis.Gcache;
    
    /** 
     * ClassName:RedisLockBase <br/> 
     * Function: TODO ADD FUNCTION. <br/> 
     * Reason:   TODO ADD REASON. <br/> 
     * Date:     2017年8月7日 上午10:16:23 <br/> 
     * @author   suchao 
     * @version   
     * @since    JDK 1.8
     * @see       
     */
    public abstract class RedisLockBase {
    	
    	/**
    	 * 日志组件
    	 */
    	private static final Logger logger = LoggerFactory.getLogger(RedisLockBase.class);
    	
    	/**
    	 * 等待超时时间
    	 */
    	private long timeout = 12000L;
    	
    	/**
    	 * 等待线程休眠时间
    	 */
    	private long threadSleep = 20L; 
    	
    	/**
    	 * 锁的有效时间
    	 */
    	private long expire = 8000L;
    	
    	private Gcache cache = null;
    	
    	/**
    	 * 放开获取redis测权限
    	* @Title: getCache  
    	* @Description: TODO
    	* @param @return
    	* @return Gcache
    	* @throws
    	 */
    	public Gcache getCache() {
    		return this.cache;
    	}
    	
    	private String timeLock = "";
    	
    	/**
    	 * 
    	* <p>Title: </p>  
    	* <p>Description: </p>  
    	* @param cache
    	* @param timeLock
    	 */
    	public RedisLockBase(Gcache cache,String timeLock) {
    		this.cache = cache;
    		this.timeLock = timeLock;
    		logger.debug("执行默认配置信息,lock:{},锁保持时间:{},获取锁的等待时间:{},获取等待休眠时间:{}",timeLock,String.valueOf(expire),String.valueOf(timeout),String.valueOf(threadSleep));
    	}
    	
    	/**
    	 * 
    	* <p>Title: </p>  
    	* <p>Description: </p>  
    	* @param cache
    	* @param timeLock
    	* @param timeout
    	* @param threadSleep
    	* @param expire
    	 */
    	public RedisLockBase(Gcache cache,String timeLock,long timeout,long threadSleep,long expire) {
    		this.cache = cache;
    		this.timeLock = timeLock;
    		this.timeout = timeout;
    		this.threadSleep = threadSleep;
    		this.expire = expire;
    		logger.debug("执行默认配置信息,lock:{},锁保持时间:{},获取锁的等待时间:{},获取等待休眠时间:{}",timeLock,String.valueOf(expire),String.valueOf(timeout),String.valueOf(threadSleep));
    	}
    	
    	
    	/**
    	 * 执行加锁事件
    	* @Title: excuteTask  
    	* @Description: TODO
    	* @param @param cache
    	* @param @param timeLock
    	* @param @throws InterruptedException
    	* @return void
    	* @throws
    	 */
    	public void excuteTask() throws InterruptedException {
    		logger.info("执行锁定任务的缓存信息,lock:{},开始执行",timeLock);
    		//执行
    		GOROOT:for(;true;){
    			//获取锁
    			String locktime = cache.get(timeLock);
    			if(locktime==null || locktime.equals("")) {
    				logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁为空,进行加锁。",timeLock);
    				//设置自己的锁时间
    				long lockSelf = new Date().getTime() + expire;
    				//设置锁
    				Long lg = cache.setnx(timeLock , String.valueOf(lockSelf));
    				if(lg.longValue()>0) {
    					//成功
    					logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁成功,setnx返回结果:{}",timeLock,Long.toString(lg));
    					//操作数据
    					funAction();
    					//获取时间
    					String time = cache.get(timeLock);
    					long nowTime = new Date().getTime();
    					if(time!= null && !time.equals("") && new Long(time).longValue()> nowTime &&  String.valueOf(lockSelf).equals(time)) {
    						//释放锁--会把别人的锁删除掉
    						cache.expire(timeLock, -1);
    						logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁成功,锁时间:{},当前时间:{},清除当前锁的LOCKKEY",timeLock,time,Long.toString(nowTime));
    					}
    					logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁成功,锁时间:{},当前时间:{}",timeLock,time,Long.toString(nowTime));
    				}else {
    					long timeouta = 0L;
    					do {
    						timeouta += threadSleep;
    						
    						//获取时间
    						String time = cache.get(timeLock);
    						long nowTime = new Date().getTime();
    						if(time==null || time.equals("") || new Long(time).longValue() < nowTime) {
    							//超出了缓存时间
    							//释放锁
    							cache.expire(timeLock, -1);
    							logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁失败,等待锁释放超时-清除锁,锁时间:{},当前时间:{}。",timeLock,time,Long.toString(nowTime));
    							continue GOROOT;
    						}
    						Thread.sleep(threadSleep);
    					}while(timeouta<timeout);
    					
    					logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁失败,等待锁超时,执行超时事件。",timeLock);
    					//等待超时
    					funTimeout();
    				}
    				
    			}else {
    				//锁存在
    				logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁存在,等待锁释放。",timeLock);
    				long timeouta = 0L;
    				do {
    					timeouta += threadSleep;
    					//获取时间
    					String time = cache.get(timeLock);
    					long nowTime = new Date().getTime();
    					if(time==null || time.equals("") || new Long(time).longValue() < nowTime) {
    						//超出了缓存时间
    						logger.debug("执行锁定任务的缓存信息,lock:{},redis锁存在-等待锁释放超时-清除锁,锁时间:{},当前时间:{}",timeLock,time,Long.toString(nowTime));
    						//释放锁
    						cache.expire(timeLock, -1);
    						continue GOROOT;
    					}
    					Thread.sleep(threadSleep);
    				}while(timeouta<timeout);
    				
    				logger.debug("执行锁定任务的缓存信息,lock:{},获取redis锁失败,等待锁超时,执行超时事件。",timeLock);
    				//等待超时
    				funTimeout();
    			}
    			//跳出整个循环
    			break;
    		}
    		logger.info("执行锁定任务的缓存信息,lock:{},执行结束。",timeLock);
    	}
    
    	
    	/**
    	 * 超时方法
    	* @Title: funTimeout  
    	* @Description: TODO
    	* @param 
    	* @return void
    	* @throws
    	 */
    	protected abstract void funTimeout();
    	
    	/**
    	 * 锁定处理事件
    	* @Title: funAction  
    	* @Description: TODO
    	* @param 
    	* @return void
    	* @throws
    	 */
    	protected abstract void funAction();
    	
    }
    

      

  • 相关阅读:
    绝对相等与弱相等
    css3之媒体查询
    css3新增选择器
    BFC渲染机制
    css优先级及其对应的权重
    滚动指示器
    web储存的初级运用
    setTimeout与setInterval的使用
    原生js获取left值和top值
    canvas圆形进度条
  • 原文地址:https://www.cnblogs.com/linuxone/p/7298779.html
Copyright © 2011-2022 走看看